簡體   English   中英

使用遞歸反向鏈表

[英]reverse linked list using recursion

我正在嘗試使用遞歸來反向鏈接列表。 我制作了reverse()函數來反轉列表。 我在main()創建了一個鏈表,還定義了print()方法。 我不知道我在犯什么錯誤。 請幫我改正。 下面給出了代碼片段。

struct node
{
    int data;
    struct node *next;
}*head;

void reverse(node **firstnode,node *n)
{
    if(n==NULL)
    {
        head=n;
        return;
    }
    reverse(&head,n->next);
    struct node *q=n->next;
    n->next=q;
    q->next=NULL;
}

void main()
{
    ......

    head=first;
    reverse(&first,first);
    print(head);
}

它可能無法直接解決您的問題。 但是,您在標記中提到了C ++ 11。 因此,請看一下std :: forward_list 它是基於單個鏈表的標准容器。

我認為您在反向功能的末尾混合了地址,它可能看起來像:

q->next=n;
n->next=NULL;

另外,我不確定是否需要“ firstnode”參數。

List* recur_rlist(List* head)
{
    List* result;
    if(!(head && head->next)) 
        return head;

    result = recur_rlist(head->next);
    head->next->next = head;
    head->next = NULL;

    return result;
}

void printList(List* head)
{
    while(head != NULL) {
        std::cout<<head->data<<" ";
        head = head->next;
    }
}
void main()
{
    List* list = createNode(2);
    append(list, createNode(3));
    append(list, createNode(4));
    append(list, createNode(5));
    append(list, createNode(6));
    List* revlist = recur_rlist(list);
    printList(revlist);
}

由於您想了解代碼,並且已經擁有許多精通代碼的資源,因此不需要更多的精制代碼示例。 我將回答一些概念,並指出需要修復的錯誤。

首先,一些背景概念。

鏈接列表:第一和休息

任何鏈表要么為空,要么可以分解為第一個(節點)和其余(一個較小的鏈表,或者為空)。 這使得遞歸容易得多。

if (head){
    node * first = head;
    node * rest  = head->next;
}

不變的(簡化的):保證在您的函數開始和結束時始終為真。

在鏈接列表中,您希望頭部指向一個節點,該節點指向另一個節點,依此類推,直到到達末尾為止(由nullptr表示)。 所有節點都不同。 所有節點均有效。 這些是在調用函數之前和函數返回時必須為真的保證。

在遞歸函數中,不變量必須保持在每一步都要反轉的子列表中,因為您在每一步都從函數中返回。 但這使遞歸更加容易,因為您要做的就是確保如果輸入正確,則函數將在當前步驟返回良好的值。

遞歸結束:通過結合前面的概念,您可以證明遞歸函數永遠不會陷入無限循環。 如果不變量保持不變,則每個步驟都將起作用,並且由於每個遞歸調用都將休息(這保證為nullptr或更短的列表),所以最終我們必須到達終點。 當然,這表明您可以應付一切。

好的,關於實際問題:

您沒有正確處理遞歸結束。 您只需在最后設置head = nullptr,我很確定那不是您想要的head。 您可能要處理if(nullptr == n-> next)的結尾,因為那樣您就知道那是最后一個節點。 當然,您仍然必須正確處理nullptr == head的瑣碎情況。

您不保留不變式。 您曾經嘗試過,但是看來您的簿記是完全錯誤的。 我建議您使用調試器或3x5記錄卡逐步完成修改交換內容的實際工作。 例如,看起來您只是在混淆此代碼片段中的哪個節點:

struct node *q=n->next;   // n is first, q is rest
// what if nullptr == q?
n->next=q;                // n->next = n->next doesn't actually change anything
q->next=NULL;             // this must already be true if reverse(rest) did its job
// q and n were swapped?

同樣,您的函數使用“ firstnode”,但不使用它,而是將全局變量“ head”設置為副作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM