扭转双向链接列表

时间:2012-06-23 04:55:56

标签: java list 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
    }
 }

8 个答案:

答案 0 :(得分:23)

让我们一次尝试几行代码。

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对于该情况为空): enter image description here

所以我们next指向A,prev指向B.我们希望这些交换。为此,我们继续将next分配给prev(指向B),现在nextprev都指向B.

    p.next=p.prev; 

大!我们到了一半。现在我们有:

Step 2

现在我们的最后一步是让prev指向next过去指向的内容。我们怎么去做呢?幸运的是,我们在next中存储了temp曾经指向的内容(换句话说,A)。所以我们用它来分配prev

    p.prev=temp; 

唉,我们有:

enter image description here

现在这个节点已被交换,我们继续前进到下一个节点。

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

答案 1 :(得分:2)

希望这会对你有所帮助。

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

}

看看这个数字。 enter image description here

希望你明白。

由于

答案 2 :(得分:1)

它只是交换列表中每个元素的prev和next指针。所以你的评论是正确的。新头的下一个指针确实以null开头。并将其复制到其prev指针。作为名单的负责人,其上一个当然应该是空的。

Vj shah的回答只是用不同的代码做同样的事情。

答案 3 :(得分: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

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

答案 4 :(得分:0)

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),这将是反转后列表中的第一个元素。

然后在迭代中删除列表的第一个元素,并在refEntry之后添加。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

为了简单起见,它也可以从头节点开始,否则算法保持不变:

private void PopulateDropdown<Type>(ComboBox control, Dictionary<Type, Type> dict)

答案 7 :(得分:0)

我用Java编写的没有递归的版本 背后的想法:首先到达列表的末尾,将此节点标记为新头,然后通过翻转连接/链接(下一个,上一个)开始向后移动,直到您不再有节点为止。

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

我希望它有所帮助。