带环的单链表

前面一篇文章介绍了单链表的一些基础操作,本文接着来看一些有环的单链表的操作。



判断单链表是否存在环,求环的入口节点,环的长度
看以下程序:

/** 链表类 */
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值