c语言判断链表是否成环,30+链表问题(一):如何判断链表是否成环?

引子

在上一篇文章《30+链表问题:概览》的引言中,我提到了当初在校招时遇到的一道链表面试题。就是这道题了。下面是问题描述以及解决方案。

问题描述

给定一个链表,如何判断该链表是否成环?

解题思路

首先,一听到这个问题,脑子一下子映出下面这幅链表成环的图:

c语言判断链表是否成环,30+链表问题(一):如何判断链表是否成环?_第1张图片

如图,上面就是一个已经成环的链表。标红的是头结点。

针对这个问题,我的解决方案是:

使用两个指针 slow、fast 遍历该链表,slow每次走一步,fast走两步(实际上,只需要两个指针一快一慢即可)。如果 fast 指针 走到头,那说明链表中不存在环。否则,两个指针在无尽的旅程中一定会相遇。

为了说明白这个情况:我还专门做了动态图(实际上,为了做这个动态图,我还花30大洋买了个软件。。。。):

c语言判断链表是否成环,30+链表问题(一):如何判断链表是否成环?_第2张图片

代码实现

这里,LinkedList是我自己定义的链表类、Node是我自己定义的结点类。源码请参考附件,或《30+链表问题:概览》。

/**

* 判断一个链表是否成环

*

* @param list 链表

* @return true Or false

*/

private boolean isContainCircle(LinkedList list) {

// 两个指针,刚开始都指向 头结点

Node slow = list.getHead();

Node fast = list.getHead();

// 如果链表成环,则直到量指针相遇之前,该循环将一直进行;

while (fast != null && fast.getNext() != null) {

/* fast 每次走两步,slow 走一步;

* 在 fast 为null 之前,slow一定不为 null */

slow = slow.getNext();

fast = fast.getNext().getNext();

// 这里直接比较其地址即可

if (slow == fast) {

return true;

}

}

return false;

}

我们写代码测试一下:

public static void main(String[] args) {

Main runner = new Main();

LinkedList list = runner.buildLinkedListWithCircle();

boolean containCircle = runner.isContainCircle(list);

System.out.println("该链表是否包含环:" + containCircle);

}

/**

* 构建出示例中的包含环的链表

*

* @return 包含环的链表

*/

private LinkedList buildLinkedListWithCircle() {

LinkedList list = new LinkedList();

Node nodeOf2 = null;

for (int i = 1; i <= 7; i++) {

Node node = new Node(String.valueOf(i) + i);

list.add(node);

if (i == 2) {

nodeOf2 = node;

}

}

list.add(nodeOf2);

return list;

}

上面构建出的链表即上面我给的图片中的链表。我们执行这段代码,得到的结果如下:

该链表是否包含环:true

如果我们备注掉 buildLinkedListWithCircle 方法中的 list.add(nodeOf2); 这一行代码,再执行,得到结果:

该链表是否包含环:false

总结

在处理链表问题的时候,双指针、多指针是常见的结题方式。这种问题见得多了,感觉都是套路。

文中代码作者只是为了做个演示,有的细节并没有做严格校验。目前没有发现有严重的错误,如果有发现问题的朋友,欢迎指出哦~希望和大家一起进步~

源码附件

参考文章

你可能感兴趣的:(c语言判断链表是否成环)