如何撤消链表?

时间:2012-01-31 09:06:19

标签: java algorithm data-structures linked-list singly-linked-list

 Node reverse(Node head) {
    Node previous = null;
    Node current = head;
    Node forward;

    while (current != null) {
        forward = current.next;
        current.next = previous;
        previous = current;
        current = forward;
    }

    return previous;
}

它究竟是如何扭转名单的?我知道它首先将第二个节点设置为forward。然后它说current.next等于null节点previous。然后它说previous现在是current。最后current成为forward

我似乎无法掌握这一点以及它的逆转方式。有人可以解释一下这是如何运作的吗?

11 个答案:

答案 0 :(得分:40)

enter image description here

答案 1 :(得分:3)

您迭代地反转列表并始终使区间[head,previous]中的列表正确反转(因此current是第一个未正确设置其链接的节点)。在每个步骤中,您执行以下操作:

  • 您还记得下一个当前节点,以便您可以继续使用
  • 您将当前的链接设置为指向上一个,如果您考虑它,这是正确的方向
  • 您将之前更改为当前,因为现在当前也正确设置了其链接
  • 您将第一个没有正确设置链接的节点更改为第一步中重新编号的节点

如果您为所有可以证明的节点(例如,感应节点)执行此操作。该列表将被正确颠倒。

答案 2 :(得分:3)

代码只是遍历列表并反转链接,直到它到达前一个尾部,它将作为新头返回。

在:

Node 1 (Head) -> Node 2 -> Node 3 -> Node 4 (Tail) -> null

后:

   null <- Node 1 (Tail) <- Node 2 <- Node 3 <- Node 4 (Head)

答案 3 :(得分:3)

public Node getLastNode( )
{
    if( next != null )
        return next.getLastNode( );
    else
        return this;
}

public Node reverse( Node source )
{
    Node reversed = source.getLastNode( );
    Node cursor = source;

    while( cursor != reversed )
    {
        reversed.addNodeAfter( cursor.getInfo( ) );
        cursor = cursor.getNodeAfter( );
    }

    source = reversed;
    return source;
}

答案 4 :(得分:2)

我称之为“樱桃采摘”。我们的想法是尽量减少掉期数量。交换发生在near和far索引之间。它是一个2-Pass算法。

    (Odd length)  A -> B -> C -> D -> E
    (Even length) A -> B -> C -> D

    Pre-Condition: N >= 2

    Pass 1: Count N, the number of elements

    Pass 2: 
            for(j=0 -> j<= (N/2 -1))
            {
              swap(j, (N-1)-j)
            }

示例1

   For above Odd length list, N = 5 and there will be two swaps 

      when j=0, swap(0, 4) //post swap state: E B C D A
      when j=1, swap(1, 3) //post swap state: E D C B A


   The mid point for odd length lists remains intact.

示例2

   For above Even length list, N = 4 and there will be two swaps 

      when j=0, swap(0, 3) //post swap state: D B C A
      when j=1, swap(1, 2) //post swap state: D C B A
  • 交换仅适用于数据,不适用于指针,可能会遗漏任何健全性检查,但您明白了。

答案 5 :(得分:0)

使用迭代反转单链表

current = head //point current pointer to head of the linked list

while(current != NULL)
{
forward = current->link; //point to the next node
fforward = forward->link; //point the next node to next node
fforward->link = forward;//1->2->3,,,,,,,,,this will point node 3 to node 2
forward->link = current; //this will point node 2 to node 1
if(current == head)
current->link = NULL;// if current pointer is head pointer it should point to NULL while reversing

current = current->link; //traversing the list
}
head = current; //make current pointer the head pointer

答案 6 :(得分:0)

  list_t *reverse(list_t *a)
  {
    list_t *progress = NULL;
    while(a)
    {
      list_t *b; //b is only a temporary variable (don't bother focusing on it)
      b = a->next;
      a->next = progress; //because a->next is assigned to another value, we must first save a->next to a different variable (to be able to use it later)
      progress = a; //progress is initially NULL (so a->next = NULL (because it is the new last element in the list))
      a = b; //we set a to b (the value we saved earlier, what a->next was before it became NULL)
      /*
        now, at next iteration, progress will equal a, and a will equal b.
        so, when I assign a->next = progress, I really say, b->next = a.
        and so what we get is: b->a->NULL.
        Maybe that gives you an idea of the picture?
        What is important here is:
          progress = a
        and
          a = b
        Because that determines what a->next will equal:
          c->b->a->0
        a's next is set to 0
        b's next is set to a
        c's next is set to b
      */
    }
    return progress;
  }

答案 7 :(得分:0)

基本思想是将头节点从第一个列表中分离出来并将其附加到第二个列表的头部。继续重复,直到第一个列表为空。

伪代码:

function reverseList(List X) RETURNS List
   Y = null
   WHILE X <> null
      t = X.next
      X.next = Y
      Y = X
      X = t
   ENDWHILE
   RETURN Y
ENDfunction

如果您希望保持原始列表不受干扰,则可以使用辅助函数递归编码复制版本。

function reverseList(List X) RETURNS List
   RETURN reverseListAux(X, null)
ENDfunction

function reverseListAux(List X, List Y) RETURNS List
   IF X = null THEN
       RETURN Y
   ELSE
       RETURN reverseListAux(X.next, makeNode(X.data, Y))
ENDfunction

请注意,辅助函数是尾递归的。这意味着您可以使用迭代创建复制反转。

function reverseList(List X) RETURNS List
   Y = null
   WHILE X <> null
     Y = makeNode(x.data, Y)
     X = X.next   
   ENDWHILE
   RETURN Y
ENDfunction

答案 8 :(得分:0)

//单链列表反转功能的实现

result_type

答案 9 :(得分:0)

最简单的思考方法是这样思考:

  1. 首先将列表的开头添加到新的链接列表中。
  2. 继续遍历原始节点,并继续在新链表的开头之前添加节点。

图:

最初:

Original List -> 1 2 3 4 5
New List -> null

第一次迭代

Original List -> 1 2 3 4 5
New List -> 1->null [head shifted to left, now newHead contains 1 and points to null]

第二次迭代

Original List -> 1 2 3 4 5
New List -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]

第三次迭代

Original List -> 1 2 3 4 5
New List ->3 -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]

现在,它一直循环直到最后。所以最终新列表变为:

  New List->  5 -> 4 -> 3 -> 2 -> 1 -> null

同一代码应如下所示(使其易于理解):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */

public ListNode reverseList(ListNode head) {
    if(head == null) {
        return null;
    }

    if(head.next == null) {
        return head;
    }

    ListNode current = head;
    ListNode previous = new ListNode(head.val);
    previous.next = null;

    while(current.next != null) {
        current = current.next;
        previous = addBeforeHead(current, previous);
    }

    return previous;
}

private ListNode addBeforeHead(ListNode node, ListNode head) {
    if (node == null) return null;
    ListNode temp = new ListNode(node.val);

    temp.next = head;
    head = temp;

    return head;
}

答案 10 :(得分:0)

这里有一个简单的函数来反转单向链表

// Defining Node structure


public class Node {
int value;
Node next;


public Node(int val) {
    
    this.value=val;
}

}

public LinkedList reverse(LinkedList list) {
    
    if(list==null) {
        
        return list;
    }
    
    Node current=list.head;
    Node previous=null;
    Node next;
    
    while(current!=null) {
        
        next=current.next;
        
        current.next=previous;
        
        previous=current;
        
        current=next;
        
    }
    
    list.head=previous;
    
    return list;
    
    
    
    
}

为了更好地理解,您可以观看此视频https://youtu.be/6SYVz-pnVwg