簡體   English   中英

扭轉雙向鏈接列表

[英]Reversing a Doubly Linked List

下面的方法反轉了具有n個元素的雙向鏈表。 我不明白這是如何工作的。 我添加了評論,如果我錯了,請糾正我。 我不確定遍歷過程是如何工作的。

 public void reverseDLL( ) {
   Node temp=head; //swap head and tail
   head=tail; // head now points to tail
   tail=temp; //tail points to head
    //traverse the list swapping prev and next fields of each node
  Node p=head; //create a node and point to head

  while(p!=null) //while p does not equal null
    { //swap prev and next of current node
      temp=p.next; // p.next does that not equal null? confusing.
      p.next=p.prev; //this line makes sense since you have to reverse the link
      p.prev=temp; //having trouble visualizing this.
      p=p.next;//advance current node which makes sense
    }
 }

讓我們一次嘗試幾行代碼。

Node temp=head;
head=tail;
tail=temp;

這里我們只是設置一些變量。 我們正在交換頭部指向尾部和尾部。

現在我們定義我們的起始節點。 這是我們的新頭,曾經是尾巴。

Node p=head; //create a node and point to head

while(p!=null)
{ 
    temp=p.next; 

在這一點上,這就是我們正在研究的內容(注意:如果這是第一次迭代, next會指向null但是沒關系,只是假設A對於那種情況為空): 在此輸入圖像描述

所以我們next指向A和prev指向B.我們希望這些交換。 為此,我們繼續並在prev (指向B) next進行分配,所以現在next並且prev將指向B.

    p.next=p.prev; 

大! 我們到了一半。 現在我們有:

第2步

現在,我們的最后一步是必須prev點什么next用來指向。 我們怎么去做呢? 幸運的是,我們在temp存儲了next用於指向的內容(換句話說,A)。 所以讓我們用它來分配prev

    p.prev=temp; 

唉,我們有:

在此輸入圖像描述

現在這個節點已被交換,我們繼續下一個節點。

    p=p.next;
}

沖洗並重復。

全部一起:

Node p=head; //create a node and point to head

while(p!=null)
{ 
    temp=p.next; 
    p.next=p.prev; 
    p.prev=temp; 
    p=p.next;
}

希望這對你有所幫助。

struct node* current = head;
struct node* next;
struct node* prev = NULL;



while (current != NULL)  //traverse the whole linked list 
{
   next  = current->next;  //temporarily store the next node
   current->next = prev;    //now assign the prev!node to next of current node
   prev = current;   //update the previous pointer
   current = next;  //update the current pointer

}

看看這個數字。 在此輸入圖像描述

希望你明白。

謝謝

它只是交換列表中每個元素的prev和next指針。 所以你的評論是正確的。 新頭的下一個指針確實以null開頭。 並將其復制到其prev指針。 作為名單的負責人,其上一個當然應該是空的。

Vj shah的回答只是用不同的代碼做同樣的事情。

這種逆轉如何運作的關鍵在於看到一個簡單的雙向鏈表在反轉之前和之后的樣子。 一旦你看到反向列表需要發生什么,該方法將更容易理解。

假設您有一個這樣的Nodes ,第一個節點為0:

node       0    1    2    3    4
data       A    L    I    S    T
next       1    2    3    4   null
prev      null  0    1    2    3

從0開始遍歷上面的節點給出輸出:ALIST

保留每個節點的數據,您可以通過交換每個節點的prev和next節點值來反轉列表:

node       0    1    2    3    4
data       A    L    I    S    T
next      null  0    1    2    3
prev       1    2    3    4   null

從4開始遍歷上面的節點給出輸出:TSILA

執行此操作的代碼很簡單,假設您有一個Node類:

public class Node {
    private char ch;
    private Node next;
    private Node prev;
}

public static Node reverse(Node trav) {
    Node swapped;
        while (trav != null) {
            swapped.next = trav.prev;
            swapped.prev = trav.next;
            trav = swap;
            trav = trav.prev;  // it was swapped so you need to follow prev
            }
        return trav  // return the new head node
}
public void reverseList(){

    Entry<E> refEntry = header.previous;
    for(int i = 0; i < size-1; i++){
        Entry<E> first = header.next;
        first.next.previous = first.previous;
        first.previous.next = first.next;

        first.previous = refEntry;
        first.next = refEntry.next;
        refEntry.next.previous = first;
        refEntry.next = first;
    }
    refEntry.previous = header;
}

該算法基本上保持一個pointer(refEntry)到該條目,該pointer(refEntry)將在反轉后成為列表中的第一個元素。

然后在迭代中刪除列表的第一個元素,並在refEntry之后添加。

使用Header Doubly Linked List,以下是我的理解。 這有幫助嗎? 它是否正確?

當電流是尾部后面的一個節點時,可以斷開循環,但為了簡單起見,讓它到達尾部。 此外,在運行循環之前,通常會檢查0或1大小的列表。

H   1   2   3   4   5   //current pointer at head
*

H   5   1   2   3   4   //bring current tail to the next of current pointer. Update current tail.
*

H   5   1   2   3   4   //advance current pointer to next
    *

H   5   4   1   2   3   //bring current tail to the next of current pointer. Update current tail.
    *

H   5   4   1   2   3   //advance current pointer to next
        *

H   5   4   3   1   2   // and so on.. 
        *

H   5   4   3   1   2
            *

H   5   4   3   2   1
            *

H   5   4   3   2   1
                *

H   5   4   3   2   1
                *

H   5   4   3   2   1   //break out when current pointer is at the tail. 
                    *

它也可以從頭節點開始,為簡單起見,否則算法保持不變:

Node currentNode=head;

while(currentNode!=null){
    Node temp = currentNode.next;
    currentNode.next=currentNode.prev;
    currentNode.prev=temp;
    currentNode=currentNode.prev;
}

我在Java Idea中寫的沒有遞歸的版本:首先到達列表的末尾,將此節點標記為新頭,然后通過翻轉連接/鏈接(下一個,上一個)開始向后移動,直到您不再有節點為止。

 Node Reverse(Node head) {
        //If List is empty or having one node
        if (head == null || head.next == null) return head;

        //Else
        Node current = head;

        //First move to the end of list
        while (current.next != null) {
            current = current.next;
        }
        //Shift head at tail of list
        head = current;

        //Let the magic begin
        while (current != null) {
                Node prev = current.prev;
                current.prev = current.next;
                current.next = prev;
                current = prev;
        }


        return head;
    }

我希望它有所幫助。

暫無
暫無

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

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