C 链表函数的几个问题
我尝试为链表创建几个函数。这些都是,但是我对函数C 链表函数的几个问题,c,recursion,struct,C,Recursion,Struct,我尝试为链表创建几个函数。这些都是,但是我对函数delete\u all和delete有问题 delete\u All需要删除具有给定值的所有元素,并且delete只需首先删除 我找不到的第一个错误是free()(在代码中标记为“HERE!!!”),当我们放入链表的head,同时在需要删除的下一个元素值中,在delete\All中也会出现无休止的程序工作 例如,(1,1,2,3,4,)无法删除第一对“1”delete和其他一些函数不能使用free函数 #include <stdlib.h&
delete\u all
和delete
有问题
delete\u All
需要删除具有给定值的所有元素,并且delete
只需首先删除
我找不到的第一个错误是
free()
(在代码中标记为“HERE!!!”),当我们放入链表的head
,同时在需要删除的下一个元素值中,在delete\All
中也会出现无休止的程序工作
例如,(1,1,2,3,4,)无法删除第一对“1”delete
和其他一些函数不能使用free
函数
#include <stdlib.h>
#include <stdio.h>
struct uzel {
int n;
struct uzel *next;
};
struct uzel *
initializef(struct uzel *head)
{
static int c = 0;
int a;
printf("uzel[%d] = ", c);
scanf("%d", &a);
if (a == 0) {
head->next = NULL;
}
else {
c++;
head->n = a;
head->next = malloc(sizeof(struct uzel));
initializef(head->next);
}
return head;
}
void
gprint(struct uzel *head)
{
printf("(");
while (head->next != NULL) {
printf("%d ", head->n);
head = head->next;
}
printf(")\n");
}
struct uzel *
delete(struct uzel *head, int val)
{
if (head->n == val) {
struct uzel *newhead = head;
newhead = head->next;
struct uzel *del = head;
// free(del);//HERE!!!!!!!!!
return newhead;
}
struct uzel *right = head;
struct uzel *left = right;
while (left->next) {
right = left->next;
if (right->next != NULL) {
if (right->n == val) {
struct uzel *del = right;
left->next = right->next;
free(del);
}
} // but here is ok!!!
left = left->next;
}
return head;
}
struct uzel *
delete_all(struct uzel *head, int val)
{
struct uzel *newhead = head;
while (newhead->n == val) {
newhead = head->next;
// struct uzel* del=head;//here!!!!!!!!!!!!!!
// free(del);
if ((newhead->n) == NULL) {
printf("No more elements to work with,ERROR");
return 0;
}
}
struct uzel *right = newhead;
struct uzel *left = newhead;
while (left->next) {
right = right->next;
if (right->n == val) {
struct uzel *tmp = right;
left->next = right->next;
free(tmp);
}
else {
left = left->next;
}
}
return newhead;
}
void
addAfter(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((left->n) != after_what) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
void
addAfterALL(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((right->next)) {
while (((left->n) != after_what)) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
}
int
main()
{
int a, b;
struct uzel head2;
struct uzel *mainhead1 = initializef(&head2);
gprint(mainhead1);
printf("Enter a number to delete: ");
scanf("%d", &a);
printf("Delete all %d ? If yes enter 2 if no enter 1: ", a);
scanf("%d", &b);
if (b == 2) {
struct uzel *mainhead = delete_all(mainhead1, a);
gprint(mainhead);
}
else {
struct uzel *mainhead = delete(mainhead1, a);
gprint(mainhead);
}
printf("Enter after what number u want to insert smth: ");
int r;
scanf("%d", &r);
printf("Enter what number u want to insert: ");
int u;
scanf("%d", &u);
printf("After all numbers %d ? If yes enter 1 If no enter 2:", r);
int g;
scanf("%d", &g);
if (g == 2) {
addAfter(u, r, mainhead1);
gprint(mainhead1);
}
if (g == 1) {
addAfterALL(u, r, mainhead1);
gprint(mainhead1);
}
}
#包括
#包括
乌泽尔结构{
int n;
结构uzel*下一步;
};
乌泽尔结构*
initializef(结构uzel*头部)
{
静态int c=0;
INTA;
printf(“uzel[%d]=”,c);
scanf(“%d”和“&a”);
如果(a==0){
head->next=NULL;
}
否则{
C++;
头部->n=a;
head->next=malloc(sizeof(struct-uzel));
初始化EF(头部->下一步);
}
回流头;
}
无效的
gprint(结构uzel*头)
{
printf(“(”);
while(head->next!=NULL){
printf(“%d”,头部->n);
头部=头部->下一步;
}
printf(“)\n”);
}
乌泽尔结构*
删除(结构uzel*头,int val)
{
如果(head->n==val){
结构uzel*newhead=head;
newhead=head->next;
结构uzel*del=头部;
//免费(del);//这里!!!!!!!!!
返回newhead;
}
结构uzel*右=头部;
结构uzel*左=右;
while(左->下一步){
右=左->下一步;
如果(右->下一步!=NULL){
如果(右->n==val){
结构uzel*del=右侧;
左->下一步=右->下一步;
免费(del);
}
}//但这里没问题!!!
左=左->下一步;
}
回流头;
}
乌泽尔结构*
全部删除(结构uzel*头,int val)
{
结构uzel*newhead=head;
while(newhead->n==val){
newhead=head->next;
//struct-uzel*del=head;//在这里!!!!!!!!!!!!!!
//免费(del);
如果((newhead->n)==NULL){
printf(“无需处理的元素,错误”);
返回0;
}
}
struct uzel*right=newhead;
结构uzel*左=新头;
while(左->下一步){
右=右->下一步;
如果(右->n==val){
结构uzel*tmp=右侧;
左->下一步=右->下一步;
免费(tmp);
}
否则{
左=左->下一步;
}
}
返回newhead;
}
无效的
addAfter(int-info,int-after\u-what,struct-uzel*head)
{
结构uzel*左=头部;
结构uzel*右=头部;
while((左->n)!=在什么之后){
右=右->下一步;
左=左->下一步;
}
右=右->下一步;
struct uzel*newelem=malloc(sizeof(struct uzel));
newelem->n=info;
newelem->next=右;
左->下一步=newelem;
}
无效的
addAfterALL(int-info,int-after\u-what,struct-uzel*head)
{
结构uzel*左=头部;
结构uzel*右=头部;
while((右->下一步)){
而((左->n)!=在什么之后){
右=右->下一步;
左=左->下一步;
}
右=右->下一步;
struct uzel*newelem=malloc(sizeof(struct uzel));
newelem->n=info;
newelem->next=右;
左->下一步=newelem;
}
}
int
main()
{
INTA,b;
结构uzel头2;
struct uzel*mainhead1=initializef(&head2);
gprint(mainhead1);
printf(“输入要删除的数字:”);
scanf(“%d”和“&a”);
printf(“删除所有%d?如果是,则输入2;如果否,则输入1:”,a);
scanf(“%d”和“b”);
如果(b==2){
struct uzel*mainhead=delete_all(mainhead1,a);
gprint(主机头);
}
否则{
struct uzel*mainhead=delete(mainhead1,a);
gprint(主机头);
}
printf(“在您要插入的数字后面输入smth:”);
INTR;
scanf(“%d”、&r);
printf(“输入要插入的数字:”);
国际大学;
scanf(“%d”和“&u”);
printf(“在所有数字%d之后?如果是,则输入1;如果否,则输入2:”,r);
int g;
scanf(“%d”和“&g”);
如果(g==2){
addAfter(u、r、mainhead1);
gprint(mainhead1);
}
如果(g==1){
添加(u、r、主标题1);
gprint(mainhead1);
}
}
删除和删除所有的代码非常相似,因此可以将其移动到通用功能
#include <stdlib.h>
#include <stdio.h>
struct uzel {
int n;
struct uzel *next;
};
struct uzel *
initializef(struct uzel *head)
{
static int c = 0;
int a;
printf("uzel[%d] = ", c);
scanf("%d", &a);
if (a == 0) {
head->next = NULL;
}
else {
c++;
head->n = a;
head->next = malloc(sizeof(struct uzel));
initializef(head->next);
}
return head;
}
void
gprint(struct uzel *head)
{
printf("(");
while (head->next != NULL) {
printf("%d ", head->n);
head = head->next;
}
printf(")\n");
}
struct uzel *
delete(struct uzel *head, int val)
{
if (head->n == val) {
struct uzel *newhead = head;
newhead = head->next;
struct uzel *del = head;
// free(del);//HERE!!!!!!!!!
return newhead;
}
struct uzel *right = head;
struct uzel *left = right;
while (left->next) {
right = left->next;
if (right->next != NULL) {
if (right->n == val) {
struct uzel *del = right;
left->next = right->next;
free(del);
}
} // but here is ok!!!
left = left->next;
}
return head;
}
struct uzel *
delete_all(struct uzel *head, int val)
{
struct uzel *newhead = head;
while (newhead->n == val) {
newhead = head->next;
// struct uzel* del=head;//here!!!!!!!!!!!!!!
// free(del);
if ((newhead->n) == NULL) {
printf("No more elements to work with,ERROR");
return 0;
}
}
struct uzel *right = newhead;
struct uzel *left = newhead;
while (left->next) {
right = right->next;
if (right->n == val) {
struct uzel *tmp = right;
left->next = right->next;
free(tmp);
}
else {
left = left->next;
}
}
return newhead;
}
void
addAfter(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((left->n) != after_what) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
void
addAfterALL(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((right->next)) {
while (((left->n) != after_what)) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
}
int
main()
{
int a, b;
struct uzel head2;
struct uzel *mainhead1 = initializef(&head2);
gprint(mainhead1);
printf("Enter a number to delete: ");
scanf("%d", &a);
printf("Delete all %d ? If yes enter 2 if no enter 1: ", a);
scanf("%d", &b);
if (b == 2) {
struct uzel *mainhead = delete_all(mainhead1, a);
gprint(mainhead);
}
else {
struct uzel *mainhead = delete(mainhead1, a);
gprint(mainhead);
}
printf("Enter after what number u want to insert smth: ");
int r;
scanf("%d", &r);
printf("Enter what number u want to insert: ");
int u;
scanf("%d", &u);
printf("After all numbers %d ? If yes enter 1 If no enter 2:", r);
int g;
scanf("%d", &g);
if (g == 2) {
addAfter(u, r, mainhead1);
gprint(mainhead1);
}
if (g == 1) {
addAfterALL(u, r, mainhead1);
gprint(mainhead1);
}
}
下面是一个重构版本(带有一些注释),它简化了删除代码,并使其适用于这两种情况
注意使用额外的next
变量来防止“空闲后使用”[这可能是调用free
]时出现问题的根源]
#include <stdlib.h>
#include <stdio.h>
struct uzel {
int n;
struct uzel *next;
};
struct uzel *
initializef(struct uzel *head)
{
static int c = 0;
int a;
printf("uzel[%d] = ", c);
scanf("%d", &a);
if (a == 0) {
head->next = NULL;
}
else {
c++;
head->n = a;
head->next = malloc(sizeof(struct uzel));
initializef(head->next);
}
return head;
}
void
gprint(struct uzel *head)
{
printf("(");
while (head->next != NULL) {
printf("%d ", head->n);
head = head->next;
}
printf(")\n");
}
struct uzel *
delete_common(struct uzel *head, int val, int allflg)
{
struct uzel *cur;
struct uzel *prev;
struct uzel *next;
prev = NULL;
for (cur = head; cur != NULL; cur = next) {
next = cur->next;
// wait for match
if (cur->n != val) {
prev = cur;
continue;
}
// remove from middle/end of list
if (prev != NULL)
prev->next = next;
// remove from head of list
else
head = next;
// release the storage for the node we're deleting
free(cur);
// stop if we're only deleting the first match
if (! allflg)
break;
}
return head;
}
struct uzel *
delete(struct uzel *head, int val)
{
head = delete_common(head,val,0);
return head;
}
struct uzel *
delete_all(struct uzel *head, int val)
{
head = delete_common(head,val,1);
return head;
}
void
addAfter(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((left->n) != after_what) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
void
addAfterALL(int info, int after_what, struct uzel *head)
{
struct uzel *left = head;
struct uzel *right = head;
while ((right->next)) {
while (((left->n) != after_what)) {
right = right->next;
left = left->next;
}
right = right->next;
struct uzel *newelem = malloc(sizeof(struct uzel));
newelem->n = info;
newelem->next = right;
left->next = newelem;
}
}
int
main()
{
int a, b;
struct uzel head2;
struct uzel *mainhead1 = initializef(&head2);
gprint(mainhead1);
printf("Enter a number to delete: ");
scanf("%d", &a);
printf("Delete all %d ? If yes enter 2 if no enter 1: ", a);
scanf("%d", &b);
if (b == 2) {
struct uzel *mainhead = delete_all(mainhead1, a);
gprint(mainhead);
}
else {
struct uzel *mainhead = delete(mainhead1, a);
gprint(mainhead);
}
printf("Enter after what number u want to insert smth: ");
int r;
scanf("%d", &r);
printf("Enter what number u want to insert: ");
int u;
scanf("%d", &u);
printf("After all numbers %d ? If yes enter 1 If no enter 2:", r);
int g;
scanf("%d", &g);
if (g == 2) {
addAfter(u, r, mainhead1);
gprint(mainhead1);
}
if (g == 1) {
addAfterALL(u, r, mainhead1);
gprint(mainhead1);
}
}
制作:
1 1 2 3 4 5 9 6 7
而不是:
1 1 2 3 4 5 9 5 6 7
同样,两个addAfter
功能可以组合和简化
关于使用列表
结构的一些附加想法
当我们传递列表指针时,调用者不必担心被调用者是否需要调整列表的标题。被调用的函数就是这样做的
在原始代码中,delete*
函数传回[可能]修改的头
。addAfter*
函数[由于其性质]无法更改列表的标题,因此它们不必返回更新后的标题值。在这两种情况下,这些函数的调用方(即main
)必须“知道”这一点
如果我们在addAfter*
中添加了一组类似的函数,这些函数在info
值之前插入(例如insertBefore*
),则它们可能必须更新头部。同样,打电话的人必须知道这一点
因此,使用struct list
实际上简化了大多数函数的代码,并允许它们具有更统一的
#include <stdlib.h>
#include <stdio.h>
struct uzel {
int n;
struct uzel *next;
};
struct list {
struct uzel *head;
};
void
initializef(struct list *list)
{
int c = 0;
int a;
struct uzel *newelem;
struct uzel *prev;
prev = NULL;
while (1) {
printf("uzel[%d] = ", c);
scanf("%d", &a);
if (a == 0)
break;
newelem = malloc(sizeof(*newelem));
newelem->n = a;
newelem->next = NULL;
if (prev != NULL)
prev->next = newelem;
else
list->head = newelem;
prev = newelem;
++c;
}
}
void
gprint(struct list *list)
{
struct uzel *cur;
printf("(");
for (cur = list->head; cur != NULL; cur = cur->next)
printf("%d ",cur->n);
printf(")\n");
}
void
delete_common(struct list *list, int val, int allflg)
{
struct uzel *cur;
struct uzel *prev;
struct uzel *next;
prev = NULL;
for (cur = list->head; cur != NULL; cur = next) {
next = cur->next;
// wait for match
if (cur->n != val) {
prev = cur;
continue;
}
// remove from middle/end of list
if (prev != NULL)
prev->next = next;
// remove from head of list
else
list->head = next;
// release the storage for the node we're deleting
free(cur);
// stop if we're only deleting the first match
if (! allflg)
break;
}
}
void
delete(struct list *list, int val)
{
delete_common(list,val,0);
}
void
delete_all(struct list *list, int val)
{
delete_common(list,val,1);
}
void
addAfter_common(struct list *list, int info, int after_what, int allflg)
{
struct uzel *cur;
struct uzel *newelem;
for (cur = list->head; cur != NULL; cur = cur->next) {
// wait for a match
if (cur->n != after_what)
continue;
// get new element to add
newelem = malloc(sizeof(*newelem));
newelem->n = info;
// insert new element after the match
newelem->next = cur->next;
cur->next = newelem;
// ensure that we don't infinitely add elements if the element value
// we're adding matches the value(s) we're searching for
// (e.g.) if info and after_what are the same
cur = newelem;
// stop unless adding after _all_ matches
if (! allflg)
break;
}
}
void
addAfter(struct list *list, int info, int after_what)
{
addAfter_common(list,info,after_what,0);
}
void
addAfterALL(struct list *list, int info, int after_what)
{
addAfter_common(list,info,after_what,1);
}
int
main(void)
{
int a, b;
struct list listx = { .head = NULL };
struct list *list = &listx;
initializef(list);
gprint(list);
printf("Enter a number to delete: ");
scanf("%d", &a);
printf("Delete all %d ? If yes enter 2 if no enter 1: ", a);
scanf("%d", &b);
if (b == 2) {
delete_all(list, a);
gprint(list);
}
else {
delete(list, a);
gprint(list);
}
printf("Enter after what number you want to insert something: ");
int r;
scanf("%d", &r);
printf("Enter what number you want to insert: ");
int u;
scanf("%d", &u);
printf("After all numbers %d ? If yes enter 1 If no enter 2:", r);
int g;
scanf("%d", &g);
if (g == 2) {
addAfter(list, u, r);
gprint(list);
}
if (g == 1) {
addAfterALL(list, u, r);
gprint(list);
}
return 0;
}