判断链路结构是否存在环

最近在公司业务中碰到了比较有趣的问题:树形结构的数据,设置父级的时候,形成了循环依赖。如:C 的父级是 B,B 的父级是 A,结果还设置了 A 的父级是 C,导致该类数据的递归运算时直接死循环后栈溢出了

有两种场景的判断方案,可以根据场景来选择

1. 链路节点单项更新的时候,判断是否有环路

  • 新增的时候,选择父级,一定是不会出现环路的,因为当前项还没有子项。删除也是,删除的时候会将当前项以及所有子项删除,不会形成新的环路。所以只需要判断更新。

  • 更新的时候,迭代去判断父级,因为父级永远只有一个,所以只要递归往上找父级,如果父级跟自己相同,则存在环路;如果父级为空,则不存在环路。

2. 直接判断所有链路节点是否存在环路

在环路中,从起点 O 开始跑,a 以 v 速度跑,b 以 2v 速度跑,则 b 跑完 2 圈的时候 a 跑完一圈,正好又在原点相遇。细品下这个逻辑~

因此判断环路存在,一定存在下面两个条件:

  1. 永远有下个节点
  2. 且 b 和 a 一定会再次相遇

具体实现如下:

public interface LinkedNode {

    LinkedNode next();
}

public class CycleCheckUtils {

    /**
     * 判断是否有循环链路
     *
     * @param linkedNode   链路节点
     * @param checkedNodes 已检查过的链路节点,如果当前链路没有环,则这些检查过的节点不需要再去判断
     * @return 是否有循环
     */
    public static boolean isCycle(LinkedNode linkedNode, List<LinkedNode> checkedNodes) {
        LinkedNode slow = linkedNode;
        LinkedNode fast = linkedNode;
        while (fast != null && fast.next() != null && fast.next().next() != null) {
            fast = fast.next().next();
            slow = slow.next();
            if (checkedNodes != null) {
                checkedNodes.add(slow);
            }
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
}
请登录后发表评论

    没有回复内容