链表循环潜在异常

时间:2017-08-19 02:17:51

标签: java linked-list nodes

下面是检测链表是否包含循环的代码:

  public static boolean containsCycle(LinkedListNode firstNode) {

// start both runners at the beginning
LinkedListNode slowRunner = firstNode;
LinkedListNode fastRunner = firstNode;

// until we hit the end of the list
while (fastRunner != null && fastRunner.next != null) {
    slowRunner = slowRunner.next;
    fastRunner = fastRunner.next.next;

    // case: fastRunner is about to "lap" slowRunner
    if (fastRunner == slowRunner) {
        return true;
    }
}

// case: fastRunner hit the end of the list
return false;

while循环的条件不应该是fastRunner!= null&& fastRunner.next.NEXT!= null?使用当前代码,fastRunner可以是链表中的最后一个节点,因此一旦输入while循环,最后一个节点的下一个节点将导致异常。

2 个答案:

答案 0 :(得分:1)

  

使用当前代码,fastRunner可以是链表中的最后一个节点

fastRunner不能是链接列表中的最后一个节点,因为您的while循环

while (fastRunner != null && fastRunner.next != null) {

检查fastRunner不是最后一个元素(因为fastRunner.next == null意味着fastRunner是最后一个元素)。循环中的这个赋值

fastRunner = fastRunner.next.next;

当然可以将fastRunner设置为null,但是你没有做任何会导致空指针异常的事情,并且while循环的下一次迭代将退出(从现在起fastRunner == null

答案 1 :(得分:0)

如果线程安全不是问题,那么这个算法肯定是正确的。  换句话说,如果在此方法运行时,另一个线程中的代码更改了列表,那么它肯定会产生不正确的结果或NullPointerException

但是,如果您的代码是单线程的,则NullPointerException无法发生。要使此代码抛出NullPointerException,必须有一个.运算符,其左侧为空值。虽然还有其他类型的代码可以抛出NullPointerException,例如自动取消装箱空值,并在for-each循环中使用空参数;你没有这些。

因此,要查看此代码可以抛出NullPointerException,您应该依次考虑代码中的每个.运算符。有四个点需要考虑。

  1. while (fastRunner != null && fastRunner.next != null) {中的点 - 这不会导致NullPointerException,因为只有当fastRunner不为空时才会检查此代码,这要归功于短路评估。
  2. slowRunner = slowRunner.next;中的点 - 这不会导致NullPointerException,因为slowRunner所采用的每个值都已由fastRunnerfastRunner.nextslowRunner。因此,如果NullPointerException为空,那么您就已经获得了fastRunner = fastRunner.next.next;。你无法从这个点获得它。
  3. NullPointerException中的第一个点 - 这不能导致fastRunner,因为您已经检查过fastRunner = fastRunner.next.next;不为空。
  4. NullPointerException中的第二个点 - 这不会导致fastRunner.next,因为您已经检查过NullPointerException不为空。
  5. 因此,代码中没有任何内容可能导致$(document).ready(function() { $("#step2").hide(); $("#step3").hide(); $("#btnsteps").click(function() { $("#step1").hide(1000, function() { $("#step2").show(1000, function() {}); }); $("#btnsteps2").click(function() { $("#step2").hide(1000, function() { $("#step3").show(1000); }); }); }); }); ,除非代码执行时第二个线程更改了列表。