大家早上好/晚上好,我想在脑海中澄清以下关于链表函数的概念(在本例中是递归的(。
让我们采用以下程序递归地消除链表中的重复项:
ElementoDiLista* deleteDuplicates(ElementoDiLista* head)
{
if (head == NULL)
{
return NULL;
}
if (head->next == NULL)
{
return head;
}
if (head->info == head->next->info)
{
ElementoDiLista *tmp;
tmp = head->next;
head->next = head->next->next;
free(tmp);
return deleteDuplicates(head);
}
else
{
head->next = deleteDuplicates(head->next);
return head;
}
}
我的结构和列表的定义是这样的:
struct el {int info; struct el *next;};
typedef struct el ElementoDiLista;
typedef ElementoDiLista *ListaDiElementi;
然后我主要这样调用函数:
Lista1 = deleteDuplicates(Lista1);
其中Lista1声明如下:ElementoDiLista Lista1 = NULL
我的问题是,我被用来声明无效或依赖于单个类型(int、float ecc…(的函数我想澄清两件事:
为什么函数被声明为
ElementoDiLista* deleteDuplicates(ElementoDiLista* head)
,因为对我来说,这种方式ListaDiElementi deleteDuplicates (ListaDiElementi *head)
更直观,但不幸的是,它不起作用。我不太清楚为什么函数返回head或NULL值,但这就是我认为为什么在主Lista1中取函数的值的原因,因为函数修改了列表本身,我是对的吗?
如果问题不是很令人兴奋,我很抱歉,我只是很难理解列表的总体内容,而且非常困难,任何帮助或建议都将不胜感激,
无论如何,谢谢大家!
为什么函数被声明为
ElementoDiLista* deleteDuplicates(ElementoDiLista* head)
,因为对我来说,这样ListaDiElementi deleteDuplicates (ListaDiElementi *head)
更直观
从参数开始,最初它被声明为,
ElementoDiLista* head
所以它取一个指向head元素的指针。这相当于(变量名称更改后(
ListaDiElementi list
所以我们传递一个"list"作为参数,它是指向头部的指针。该指针未被修改。为了修改它,我们确实需要按照你的建议使用
ElementoDiLista** head
或者等效地并且可能更可读的
ListaDiElementi* list
因此,问题是,"我们需要修改指向头部的指针吗">或者换句话说,是否需要修改原始列表指针?答案是否。
如果列表为空,则它将保持为空。如果列表不为空,则标题将保持不变。不会移除头,只移除后面的节点,这些节点的值与头的值相同。
我不太清楚为什么函数返回head或NULL值,但这就是我认为为什么在主Lista1中取函数的值的原因,因为函数修改了列表本身,我是对的吗?
就我个人而言,我不喜欢函数返回指向元素(即列表(的指针。此外,它似乎总是返回head
,并且以一种相当模糊的方式实现。
首先是关于我不喜欢它。如果你正在更改现有列表的结构,而不是创建一个新列表,你希望你的初始指针在过程后保持有效。因此,您可以更改该指针(如果需要(,而不是返回一个新指针。在这种情况下,它甚至没有改变。所以我要么用void
,要么返回一些退出代码。
其次看代码,
if (head == NULL) { return NULL;
它返回head
,因为它为空。
if (head->next == NULL) { return head;
它再次返回头部。
if (head->info == head->next->info) { ElementoDiLista *tmp; tmp = head->next; head->next = head->next->next; free(tmp); return deleteDuplicates(head); }
它返回deleteDuplicates(head)
,而head
是未更改的原始参数。所以,如果所有其他情况都返回头部,那么这也会返回头部。
else { head->next = deleteDuplicates(head->next); return head; }
这也返回head
(注意head
没有更改(。所以它的返回值总是原始参数head
。所以这毫无意义。
此外,请注意,在前两种情况下,您什么都不做,只返回一个无用的值。
if (head == NULL) { return NULL; } if (head->next == NULL) { return head; }
因此,如果您将过程更改为void
,则此代码将消失。如果您的列表或其尾部为空,则无需执行任何操作,因为不存在重复项。