Reversing a Doubly Linked List

瘦欲@ 提交于 2019-12-19 03:14:13

问题


This method right below reverses a doubly linked list with n elements. I dont understand how this really works. I have added comments, please correct me if I am wrong. I am not sure how the traversing process works.

 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
    }
 }

回答1:


Let's try stepping through the code a few lines at a time.

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

Here we are just setting up some variables. We are swapping our head to point to the tail and the tail to the head.

Now we define our starting node. This is our new head that used to be the tail.

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

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

At this point, this is what we are looking at (note: if this is the first iteration, next would point to null but that doesn't matter, just assume A is null for that case):

So we have next pointing to A and prev pointing to B. We want these to be swapped. To do so, we go ahead and assign next to prev (which points to B) so now next and prev both point to B.

    p.next=p.prev; 

Great! We're half way there. Now we have:

Now our last step is to have prev point to what next used to point to. How are we going to get to it? Luckily, we stored what next used to point to (in other words, A) in temp. So let's use that to assign prev.

    p.prev=temp; 

Alas, we have:

Now this node has been swapped, and we move on to the next.

    p=p.next;
}

Rinse and repeat.

All together:

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;
}



回答2:


Hope this helps you.

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

}

Look at this figure.

Hope you get it.

Thanks




回答3:


It's just swapping the prev and next pointers in every element of the list. So your comment is correct. The new head's next pointer does start as null. And it gets copied to its prev pointer. As the head of the list its prev should of course be null.

Vj shah's answer does the same thing just with different code.




回答4:


The key to how this reversal works is see what a simple doubly linked list looks like before and after it is reversed. Once you see what needs to happen to reverse the list, the method will be easier to understand.

Suppose you had a Nodes like this with the first node at 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

Traversing the nodes above starting at 0 gives the output: ALIST

Leaving the data of each each node in place, you can reverse the list by swapping the prev and next node values for each node:

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

Traversing the nodes above starting at 4 gives the output: TSILA

The code to do this is simple assuming you have a Node class as such:

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
}



回答5:


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;
}

The algorithm basically maintains a pointer(refEntry) to the entry which is going to be the first element in the list after reversal.

The first element of the list is then removed in iterations and added after the refEntry.




回答6:


With a Header Doubly Linked List, following is what I understand. Does this help? Is this correct?

The loop may be broken out when current is one node behind tail, but for simplicity, let it reach the tail. Also, the usual checks for 0 or 1 sized list come before running the loop.

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. 
                    *



回答7:


It can be started from head node also for simplicity, otherwise the algorithm remains the same:

Node currentNode=head;

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



回答8:


My version without recursion that I wrote in Java Idea behind: Reach the end of list first, mark this node as new head, then start moving backwards direction by flipping connections/Links (next, prev) till you have left no more node.

 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;
    }

I hope it helps.



来源:https://stackoverflow.com/questions/11166968/reversing-a-doubly-linked-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!