链表中环的入口结点

链表中环的入口结点

题目:如果一个链表中包含环,如何找出环的入口点?例如:下图所示的链表,环的入口结点是结点3
在这里插入图片描述

解决这个问题的第一步是如何确定一个链表中包含环。
一个包含环的链表,一直向前遍历是无穷次的。那么我们可以用两个快慢指针来解决这个问题。
定义两个指针,一个一次走一步,另一个一次走两步。如果快指针追上了慢指针,那么表示链表有环。如果快指针到达链表尾部(next域为空),说明链表无环。

确定链表有环之后,我们接下来就是找环的入口了。
我们可以用两个指针来解决这个问题。先定义两个指针p1和p2指向链表的头结点。如果链表中的环有n个结点,则p1现在链表上向前移动n步,然后两个指针以相同的速度,一次向前移动一步,当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈,又回到了入口结点。这种思路类似于找链表中倒数第k个结点的思路,入口结点是第k个结点,也是尾部结点。

而如何求环中有几个结点呢?
我们在前面确定环是否存在时,快慢指针相遇的位置必定在环内。我们只需再定义一个指针,在环内绕一圈,即可统计环内结点的个数。

代码示例:

//找相遇结点,无环返回空指针
HeadList* MeetingNode(HeadList* head)
{
	if (head == NULL) exit(0);

	HeadList* pSlow = head->next;
	HeadList* pFast = NULL;
	if (pSlow)
		pFast = head->next->next;

	while (pSlow != NULL && pFast != NULL && pFast->next != NULL)
	{
		if (pSlow == pFast)
			return pSlow;

		pSlow = pSlow->next;
		pFast = pFast->next->next;
	}
	return NULL;
}

//找环入口结点
HeadList* EntryNodeOfLoop(HeadList* head)
{
	HeadList* meetingNode = MeetingNode(head);
	if (meetingNode == NULL) return NULL;

	int nodeInLoop = 1;
	HeadList* p1 = meetingNode;
	while (p1->next != meetingNode)
	{
		p1 = p1->next;
		nodeInLoop++;
	}
	p1 = head;
	for (int i = 0; i < nodeInLoop; ++i)
		p1 = p1->next;

	HeadList* p2 = head;
	while (p1 != p2)
	{
		p1 = p1->next;
		p2 = p2->next;
	}
	return p1;
}

测试代码:带头结点单链表的C语言代码实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_200_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值