繁体   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