C 使用递归删除链表中出现的所有数字
我想写一个程序,使用递归从一个简单的链表中删除一个数字的所有匹配项,所以我尝试了,但我遇到了问题:我写的程序删除了列表中的所有匹配项,但它不删除一个存在于开始的匹配项存在于第一个节点,下面是C中的代码:C 使用递归删除链表中出现的所有数字,c,algorithm,recursion,linked-list,C,Algorithm,Recursion,Linked List,我想写一个程序,使用递归从一个简单的链表中删除一个数字的所有匹配项,所以我尝试了,但我遇到了问题:我写的程序删除了列表中的所有匹配项,但它不删除一个存在于开始的匹配项存在于第一个节点,下面是C中的代码: typedef struct list { int data; struct list *next; } list; list *delete(int x, list *head) { if (head->next == NULL) return
typedef struct list {
int data;
struct list *next;
} list;
list *delete(int x, list *head) {
if (head->next == NULL)
return head;
list *newnode = delete(x, head->next);
if (newnode->data == x) {
head->next = head->next->next;
free(newnode);
}
return head;
}
我希望有人能帮助我改进算法,提前谢谢。此代码:
if(head->next == NULL)
return head;
显式使函数返回的任何1元素列表保持不变。这就产生了你所描述的问题,因此没有任何意义
我想应该可以递归地对列表元素进行删除,尽管这肯定不是一种常见/典型/好的方法
这可能有效,但未经测试:
list * delete(list *head, int value)
{
if (head == NULL)
return NULL;
if (head->data == value)
{
list * tail = head->next;
free(head);
return delete(tail, value);
}
// List was not empty and did not start with the value,
// so set the tail of the list to the tail without the value.
head->next = delete(head->next, value);
return head;
}
此代码:
if(head->next == NULL)
return head;
显式使函数返回的任何1元素列表保持不变。这就产生了你所描述的问题,因此没有任何意义
我想应该可以递归地对列表元素进行删除,尽管这肯定不是一种常见/典型/好的方法
这可能有效,但未经测试:
list * delete(list *head, int value)
{
if (head == NULL)
return NULL;
if (head->data == value)
{
list * tail = head->next;
free(head);
return delete(tail, value);
}
// List was not empty and did not start with the value,
// so set the tail of the list to the tail without the value.
head->next = delete(head->next, value);
return head;
}
如果没有,它将删除第一个节点上存在的引用开始时存在的引用
这是因为以下几行:
如果只返回一个元素,而不管理它可以包含要删除的数据这一事实,则返回该元素
您不需要有delete的递归定义,最糟糕的是使用非终端递归
还可以添加工作函数以检查执行情况:
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
int data;
struct list* next;
} list;
list* delete(int x, list* head)
{
list ** p = &head;
while (*p != NULL) {
if ((*p)->data == x) {
list * d = *p;
*p = (*p)->next;
free(d);
}
else
p = &(*p)->next;
}
return head;
}
void print(list * l)
{
if (l == NULL)
puts("<empty>");
else {
do {
printf("%d ", l->data);
l = l->next;
} while (l != NULL);
putchar('\n');
}
}
list * make(int data, list * next)
{
list * l = malloc(sizeof(list));
l->data = data;
l->next = next;
return l;
}
int main(int argc, char ** argv)
{
list * head = make(1, make(2, make(1, NULL)));
print(head);
head = delete(1, head);
print(head);
head = delete(2, head);
print(head);
return 0;
}
汇编和执行:
/tmp % gcc -Wall l.c
/tmp % ./a.out
1 2 1
2
<empty>
/tmp %
在valgrind下:
如果没有,它将删除第一个节点上存在的引用开始时存在的引用
这是因为以下几行:
如果只返回一个元素,而不管理它可以包含要删除的数据这一事实,则返回该元素
您不需要有delete的递归定义,最糟糕的是使用非终端递归
还可以添加工作函数以检查执行情况:
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
int data;
struct list* next;
} list;
list* delete(int x, list* head)
{
list ** p = &head;
while (*p != NULL) {
if ((*p)->data == x) {
list * d = *p;
*p = (*p)->next;
free(d);
}
else
p = &(*p)->next;
}
return head;
}
void print(list * l)
{
if (l == NULL)
puts("<empty>");
else {
do {
printf("%d ", l->data);
l = l->next;
} while (l != NULL);
putchar('\n');
}
}
list * make(int data, list * next)
{
list * l = malloc(sizeof(list));
l->data = data;
l->next = next;
return l;
}
int main(int argc, char ** argv)
{
list * head = make(1, make(2, make(1, NULL)));
print(head);
head = delete(1, head);
print(head);
head = delete(2, head);
print(head);
return 0;
}
汇编和执行:
/tmp % gcc -Wall l.c
/tmp % ./a.out
1 2 1
2
<empty>
/tmp %
在valgrind下:
代码中存在多个问题: 您在不首先检查head是否为NULL的情况下解除对其的引用。该函数无法处理空列表。 如果列表中只有一个元素,则显式返回head节点而不测试其值。 在head->next上递归后,只测试列表的第二个元素。因此,第一个元素从未经过测试。 下面是一个修改版本,它只测试第一个节点,并递归列表的其余部分: 列表*删除点x,列表*标题{ 如果head==NULL 回流头; 如果磁头->数据==x{ 列表*节点=头; 头部=头部->下一步; 自由节点; 返回deletex,head; } head->next=deletex,head->next; 回流头; }
代码中存在多个问题: 您在不首先检查head是否为NULL的情况下解除对其的引用。该函数无法处理空列表。 如果列表中只有一个元素,则显式返回head节点而不测试其值。 在head->next上递归后,只测试列表的第二个元素。因此,第一个元素从未经过测试。 下面是一个修改版本,它只测试第一个节点,并递归列表的其余部分: 列表*删除点x,列表*标题{ 如果head==NULL 回流头; 如果磁头->数据==x{ 列表*节点=头; 头部=头部->下一步; 自由节点; 返回deletex,head; } head->next=deletex,head->next; 回流头; }
有点离题挑剔:请不要使用术语C/C++。没有这样的语言,只有两种非常不同的语言C和C++。如果你用C语言编程,那么只标记C语言标记。使用递归迭代链表有什么意义?请提供一个你没有删除的链接,因为行ifhead->next==NULL返回head;在这里使用递归是完全错误的。1.效率较低。2如果你的链表很长,你会遇到麻烦。3.迭代版本更容易编写。扔掉这个函数,在没有递归的情况下正确地重写它。有点离题:请不要使用术语C/C++。没有这样的语言,只有两种非常不同的语言C和C++。如果你用C语言编程,那么只标记C语言标记。使用递归迭代链表有什么意义?请提供一个你没有删除的链接,因为行ifhead->next==NULL返回head;在这里使用递归是完全错误的。1.效率较低。2如果你的链表很长,你会遇到麻烦。3.迭代版本更容易编写。扔掉函数并正确地重写它,而不使用递归。