簡體   English   中英

遞歸反向鏈接列表

[英]Reverse Linked List Recursively

我在鏈接列表中定義了一個節點:

typedef struct abc
{
    int id;
    struct abc *next;        
}node;

我想以遞歸方式反轉鏈接列表。我將頭指針傳遞給函數。 我的函數定義如下:

node *reverseLinkedListRecursively(node *head)
{
    node *current;
    node *rest;
    if(head == NULL)
        return head;

    current=head;
    rest=head->next;

    if(rest == NULL)
    {
       return rest;
    }
    reverseLinkedListRecursively(rest);
    current->next->next=rest;
    current->next=NULL;
    return rest;
}

我該怎么辦? 我已經實現了迭代方法。

它應該如下工作:

node *reverseLinkedListRecursively(node *rest, node *reversed)
{
    node *current;

    if (rest == NULL)
        return reversed;

    current = rest;
    rest = rest->next;
    current->next = reversed;

    return reverseLinkedListRecursively(rest, current);
}

最初,啟動它:

reverseLinkedListRecursively(linkedList, NULL);

BTW:這個函數是尾遞歸的。 因此,最先進的編譯器應該能夠將這種遞歸解決方案轉變為更有效的迭代解決方案。

node *reverseLinkedListRecursively(node *head)
{
    node *current;
    node *rest;
    if(head == NULL)
        return head;


    current=head;
    rest=head->next;

    if(rest == NULL)
    {
        /* Wrong. Think about the simple case of a one-element list.
           Your code will return NULL as the reversed list. */
        //return rest;
        return current;
    }
    /* You lost the return value, which will be the beginning of the reversed 'rest'. */
    //reverseLinkedListRecursively(rest);
    rest = reverseLinkedListRecursively(rest);

    /* current->next points to the last element in the reversed 'rest'.
       What do you want that to point to? */
    //current->next->next=rest;
    current->next->next = current; // temporarily circular
    current->next=NULL;

    /* Now you can return rest, since you set it to the beginning of the reversed list. */
    return rest;
}

為了遞歸地反轉鏈表,我們反轉(遞歸地)包含除第一個節點之外的所有內容的子列表,然后將第一個節點放在最后。 要將第一個節點放在最后,我們需要遞歸調用來返回指向最后一個節點的指針,以便我們可以訪問它的next成員。 當子列表為null時,我們停止遞歸,只返回當前節點。 在我們將第一個節點附加到遞歸調用結果的末尾之后,當我們從當前遞歸調用返回時,第一個節點是“最后一個節點”。 最后一個細節是:原始的第一個節點(現在是最后一個節點)仍將指向原始的第二個節點(現在是倒數第二個節點)。 我們需要將其修復為null,因為它現在是列表的末尾。

從而:

node* reverseLinkedListHelper(node* head) {
    if (head->next == NULL) { return head; }
    node* last = reverseLinkedListRecursively(head->next);
    last->next = head;
    return head;
}

void reverseLinkedList(node* head) {
    assert (head != NULL);
    reverseLinkedListHelper(head);
    head->next = NULL;
}

還有一個問題,我會讓你思考:我們如何獲得指向列表頭的指針? :)

對於每次遞歸,請跟蹤當前節點和其余節點的前端。 當其余為NULL時返回。 遞歸返回后,將“rest”的下一個字段反轉為指向當前。 為了跟蹤新的第一個節點,遞歸函數只是將舊的最后一個節點傳回。

void recursive_reverse() {
    // driver for the recursive reverse function.
    // first is a data member of linked list that point to the first node of list.
    first = recursive_reverse(first, first->next);
}

Node* recursive_reverse(Node *current, Node *rest) {
    // if rest == NULL, the current must be the old last node,
    // which is also the new first node
    if (rest == NULL) return current;
    Node *new_first = recursive_reverse(current->next, rest->next);

    // rearrange pointers
    rest->next = current;
    current->next = NULL;

    // pass along the new first node
    return new_first;
}

我的原始實現使用了一個sentinel節點,所以我沒有在這里測試代碼。 抱歉! 只需將其讀作偽代碼即可。

void RecursiveReverse(struct node** headRef)  
{  
    struct node* first;  
    struct node* rest; 

    if (*headRef == NULL) return; // empty list base case

    first = *headRef; // suppose first = {1, 2, 3}
    rest = first->next; // rest = {2, 3}

    if (rest == NULL) return; // empty rest base case
    RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case after: rest = {3, 2}

    first->next->next = first; // put the first elem on the end of the list
    first->next = NULL; // (tricky step -- make a drawing)

    *headRef = rest; // fix the head pointer
}

嘿伙計們在下面找到了帶有和不帶遞歸的鏈表的程序,希望這對你有所幫助。

LINK *reverse_linked_list_recursion(LINK *head)
{
        LINK *temp;
        if (!head) {
                printf("Empty list\n");
                return head;
        }
        else if (!head->next)
                return head;
        temp = reverse_linked_list_recursion(head->next);
        head->next->next = head;
        head->next = NULL;
        return temp;
}

LINK *reverse_linked_list_without_recursion(LINK *head)
{
        LINK *new, *temp;
        if (!head) {
                printf("No element in the list\n");
                return head;
        }
        else {
                new = head;
                while (head->next) {
                        temp = head->next;
                        head->next = temp->next;
                        temp->next = new;
                        new = temp;
                }
        }
        return new;
}

如果要反轉列表,則必須在節點結構中包含先前的節點指針:

typedef struct abc
{
    int id;
    struct abc *next;
    struct abc *prev;        
}node;

你的清單必須有指向頭尾的指針:

typedef struct list
{
    node * first;
    node * last;
} list;

暫無
暫無

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

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