求带环的单链表入口位置处的节点

题目:如本文题目,给定一个带环的单链表,给出一个算法求链表环的入口位置处的节点。


解析:这题的解决步骤如下:

1.设置一个快指针fast和一个慢指针slow,它们同时从链表头开始往后遍历,快指针每次移动两个位置,慢指针每次移动一个位置

2.当快指针和慢指针相遇时,将慢指针重新指向链表头

3.快指针和慢指针此时在同时移动,两个指针都一次移动一个位置,当两个指针再次相遇时,指针所指的节点即入口节点。

之所以这样能够定位环的入口节点,原因解析如下:

假设链表头节点为head,环入口节点为entrance,并假设有head到entrance共有n个节点(包括head,

但不包括entrance),环的节点个数为m。我们知道,快指针和慢指针第一次相遇的节点肯定在环中,

假设从entrance到这个节点共k个节点(包括entrance和相遇的节点)。那么此时slow指针共移动了 

n+k 个节点,fast指针共移动了 2*(n+k) 个节点。则有 2*(n+k) = n + k + x*m,其中x

表示此时fast指针已经在环中绕的圈数。由此可以得到 n+k=x*m,即 n = (x-1)*m + m - k

。那么此时再将慢指针重新指向head,并且slow指针和fast指针均以同样的速度,每次移动一个节点

位置往后移动,那么当slow指针走到entrance时,fast指针同样移动到了entrance节点。

代码如下:
SListNode* FindBeginning(SListNode* head)
{
	if (head == NULL)
	{
		return NULL;
	}
	SListNode* fast = head;
	SListNode* slow = head;
	while (1)
	{
		fast = fast->next->next;
		slow = slow->next;
		if (fast == slow)
		{
			break;
		}
	}
	slow = head;
	while (fast != slow)
	{
		fast = fast->next;
		slow = slow->next;
	}

	return fast;
}

测试用例如下:

void Test14()
{

		SListNode *seq = NULL;
	
		PushBack(seq, 1);
		PushBack(seq, 2);
		PushBack(seq, 3);
		PushBack(seq, 4);
		PushBack(seq, 5);
		PushBack(seq, 6);
		PushBack(seq, 7);
		PushBack(seq, 8);
		PushBack(seq, 9);
		PushBack(seq, 10);
		
		SListNode * address1 = Find(seq, 10); //将节点10的地址返回给address1
		SListNode * address2 = Find(seq, 6);  //将节点6的地址返回给address2
		address1->next = address2;      //节点10就会指向节点6,这样就形成一个环
		
		SListNode* ret=FindBeginning(seq);  //利用函数返回环入口节点地址给ret

		cout << "入口节点是 "<<ret->date << endl;  //输出环入口节点的数据
	
}

运行结果如下:

wKioL1bZIluDwPk2AAAR-IVB7Ow411.png










本文出自 “零点时光” 博客,请务必保留此出处http://10741764.blog.51cto.com/10731764/1747533

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值