[英]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:
现在我们有:
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.