了解链接列表的类型函数

时间:2018-12-02 11:26:13

标签: c function recursion linked-list singly-linked-list

早上好/大家晚上好, 我想在脑海中阐明以下有关链表函数的概念(在这种情况下是递归的)。

让我们采用以下程序来递归地消除链接列表中的重复项:

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 ...) 我想澄清两件事:

  1. 为什么将函数声明为ElementoDiLista* deleteDuplicates(ElementoDiLista* head),因为对我来说,它更直观ListaDiElementi deleteDuplicates (ListaDiElementi *head),但不幸的是,它不起作用。

  2. 我不太清楚为什么该函数返回head或NULL值,但这就是我认为为什么在主Lista1中采用该函数值的原因,因为该函数会修改列表本身,我说的对吗?

很抱歉,如果这些问题不是很令人兴奋,我只是想尽全力理解列表,而且很难, 任何帮助或建议,将不胜感激,

还是谢谢你!

1 个答案:

答案 0 :(得分:1)

  

为什么将函数声明为ElementoDiLista* deleteDuplicates(ElementoDiLista* head),因为对我而言,它更直观ListaDiElementi deleteDuplicates (ListaDiElementi *head)

从参数开始,最初将其声明为

ElementoDiLista* head

因此它需要一个指向head元素的指针。等效于

(更改了变量名)
ListaDiElementi list 

因此,我们将“ list”作为参数传递,该“ list”是指向头部的指针。该指针未修改。确实要对其进行修改,我们需要按照您的建议使用

ElementoDiLista** head

或等效的,也许更易读,

ListaDiElementi* list 

因此,问题是“我们需要修改指向头部的指针”吗?或者换句话说,是否需要修改原始列表指针?答案是

如果列表为空,它将保持为空。如果列表不为null,则头部将保持不变。您将不会移除头部,仅移除其后的节点具有与头部相同的值。

  

我不太清楚为什么该函数返回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,此代码将消失。如果列表或其尾部为null,则无需执行任何操作,因为没有重复项。