繁体   English   中英

为什么我不能以这种方式反转链表而不会出现 null 指针异常?

[英]Why can't I reverse a linked list in this way without getting a null pointer exception?

这是我在这里的第一个问题。 这可能是一个愚蠢的问题,但我无法理解为什么在以这种方式反转链表时顺序特别重要。 所以在这里我正在反转一个链表,它有效

    ListNode prev = null, curr = head, next = head;
    
    while (curr != null){
        next = next.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    head = prev;
    return head;

效果很好。 但是为什么我不能执行以下操作?

//edge cases:
    if (head == null || head.next == null){
        return head;
    }
    
    ListNode prev = null, curr = head, next = head.next; //change here
    
    while (curr != null){
        //line was previously here
        curr.next = prev;
        prev = curr;
        curr = next;
        next = next.next; //moved here
    }
    head = prev;
    return head;

为什么我在 while 循环的开头而不是结尾设置 next = next.next 很重要? 为什么我不能先设置 next = head.next 然后在循环结束时对其进行迭代而不会出现 null 指针异常?

只是为了记录,您可以将反向操作视为从输入列表中弹出并推送到结果。 更少的史诗代码结果:

ListNode reverse(ListNode head) {
  ListNode result = null;
  while (head != null) {
    ListNode elt = head;  // pop into elt
    head = head.next;
    elt.next = result;    // push elt onto result
    result = elt;
  }
  return result;
}

当您进行此类更改时,您更改了将验证循环条件的 state。 这导致了这个问题。

在工作代码中,我们有这个循环不变量:

currnext是相等的。 它们要么都是null要么都引用同一个节点。

在非工作代码中,这是不正确的,因为现在next是领先一步。 相应的循环不变量现在是next == curr.next 所以当curr是尾节点时, next将是null 在循环的下一次迭代中,执行next = next.next ,这是无效的,因为nextnull ,所以这会引发异常。

如果您将该语句设为有条件的,它将起作用:

 if (next != null) next = next.next;

或者这也可以:

 if (next == null) break;
 next = next.next;

但是这两种选择都没有原始代码那么优雅,因为现在每次迭代都要进行两次检查(循环条件和这个额外的检查)。 事实上,这个额外的检查只是循环条件的重复,因为此时nextcurr相等。

暂无
暂无

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

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