简体   繁体   English

扭转双向链接列表

[英]Reversing a Doubly Linked List

This method right below reverses a doubly linked list with n elements. 下面的方法反转了具有n个元素的双向链表。 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
    }
 }

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): 在这一点上,这就是我们正在研究的内容(注意:如果这是第一次迭代, next会指向null但是没关系,只是假设A对于那种情况为空): 在此输入图像描述

So we have next pointing to A and prev pointing to B. We want these to be swapped. 所以我们next指向A和prev指向B.我们希望这些交换。 To do so, we go ahead and assign next to prev (which points to B) so now next and prev both point to B. 为此,我们继续并在prev (指向B) next进行分配,所以现在next并且prev将指向B.

    p.next=p.prev; 

Great! 大! We're half way there. 我们到了一半。 Now we have: 现在我们有:

第2步

Now our last step is to have prev point to what next used to point to. 现在,我们的最后一步是必须prev点什么next用来指向。 How are we going to get to it? 我们怎么去做呢? Luckily, we stored what next used to point to (in other words, A) in temp . 幸运的是,我们在temp存储了next用于指向的内容(换句话说,A)。 So let's use that to assign prev . 所以让我们用它来分配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;
}

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

It's just swapping the prev and next pointers in every element of the list. 它只是交换列表中每个元素的prev和next指针。 So your comment is correct. 所以你的评论是正确的。 The new head's next pointer does start as null. 新头的下一个指针确实以null开头。 And it gets copied to its prev pointer. 并将其复制到其prev指针。 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. Vj shah的回答只是用不同的代码做同样的事情。

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: 假设您有一个这样的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

Traversing the nodes above starting at 0 gives the output: ALIST 从0开始遍历上面的节点给出输出: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: 保留每个节点的数据,您可以通过交换每个节点的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

Traversing the nodes above starting at 4 gives the output: TSILA 从4开始遍历上面的节点给出输出:TSILA

The code to do this is simple assuming you have a Node class as such: 执行此操作的代码很简单,假设您有一个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;
}

The algorithm basically maintains a pointer(refEntry) to the entry which is going to be the first element in the list after reversal. 该算法基本上保持一个pointer(refEntry)到该条目,该pointer(refEntry)将在反转后成为列表中的第一个元素。

The first element of the list is then removed in iterations and added after the refEntry . 然后在迭代中删除列表的第一个元素,并在refEntry之后添加。

With a Header Doubly Linked List, following is what I understand. 使用Header Doubly Linked List,以下是我的理解。 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. 此外,在运行循环之前,通常会检查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. 
                    *

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

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. 我在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;
    }

I hope it helps. 我希望它有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM