前面一篇文章介绍了单链表的一些基础操作,本文接着来看一些有环的单链表的操作。
判断单链表是否存在环,求环的入口节点,环的长度
看以下程序:
/** 链表类 */
class LinkQueue{
Entry head = new Entry();
/** 节点类,用于节点初始化 */
class Entry{
int data;
Entry next;
public Entry() {
data = -1;
next = null;
}
public Entry(int data) {
this.data = data;
next = null;
}
}
/** 头插法 */
public void insertHead(int data) {
Entry cur = new Entry(data);
cur.next = head.next;
head.next = cur;
/** 先制作一个带环的链表 */
public void makeLoop() {
Entry cur = head;
while (cur.next != null) {
cur = cur.next;
}
// 设置环的开始节点是链表的第二个节点
cur.next = head.next.next;
}
/** 判断是否是环 */
public boolean isLoop() {
// 定义快慢两个指针
Entry fast = head;
Entry slow = head;
// 若两个指针能够相遇,则说明有环
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) {
return true;
}
}
return false;
}
/** 找环的开始节点 */
public int startLoop() {
// 定义两个快慢指针
Entry fast = head;
Entry slow = head;
// 两指针相遇则有环
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow =slow.next;
if(slow == fast) {
break;
}
}
// 此时让一个指针回到头节点重新遍历,另一个指针以相同速度从相遇点开始遍历
slow = head;
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
// 两指针再次相遇的节点就是环开始的节点
return fast.data;
}
/** 求环的长度 */
public int getLoopLength1() {
int len = 0;
// 定义快慢指针和一个标志位
boolean flag = false;
Entry fast = head;
Entry slow = head;
// 如果没有环就返回-1
if (!isLoop()) {
return -1;
}
while (fast.next != null && fast.next.next != null) {
// 找到两指针第一次相遇的节点
fast = fast.next.next;
slow = slow.next;
// 设置结束条件为第三次快慢指针相遇
if (slow == fast && flag == true) {
break;
}
// 两指针第二次相遇时设置标志位
if (slow == fast && flag == false) {
flag = true;
}
// 两指针第二次相遇后用慢指针计算长度
if (flag == true) {
len++;
}
}
return len;
}
}
用一个例子来验证:
public class LinkQueueTest {
public static void main(String [] args) {
// 动态制作一个链表
Link link = new Link();
for (int x = 0; x < 10; x++) {
link.insertHead(x);
}
// 制作环
link.makeLoop();
System.out.println(link.isLoop()? "is loop":"is not loop");
System.out.println("环的起点是: " + link.startLoop());
System.out.println("方式二取得环的长度是: " + link.getLoopLength1());
}
}
以上程序的结果是:
is loop
环的起点是: 8
得环的长度是: 9