查找链表中环的入口节点----测试用例

链表中环的入口几点

题目:一个链表中包含环,如何找出环的入口结点?例如,在链表中, 环的入口结点是结点3。

分析:(1)首先我们要确定链表是否有环,可以考虑使用双指针来确定。定义两个指针,同时从链表的头部出发,第一个指针走一步,第二个指针一次走二步。如果走的快的指针追上了走的慢的指针,那么就证明链表有环。如果走的快的指针走到了链表的末尾(m_pnext指向NULL)都没有追上第一个指针,那么表示无环。
(2)找到环的入口。还是可以用2个指针来解决问题。先定义两个指针p1和p2指向链表的头结点,。如果链表环中有n个几点,那么p1指针先走n步,然后两个指针再以相同的速度往前走。直到相遇,则是入口节点。看图!!!
在这里插入图片描述
(3)如何确定环中节点数。再判断是否有环时用到了2个指针。两个指针相遇的节点一定在此环中。可以从这个节点出发,定义个pNode,然后一边走一边计数,当再次回到这个节点,即得到了环中的节点数。
代码:


//首先需要确定链表是否有环。即要确定两个指针相遇的节点
ListNode* MeetingNode(ListNode *phead)
{
	if (phead == nullptr)
	{
		return nullptr;
	}

	ListNode* pSlow = phead->m_pNext; //慢指针一次走一步

	if (pSlow == nullptr)
	{
		return nullptr;
	}

	ListNode* pFast = pSlow->m_pNext; //快指针比慢指针快走两步

	while (pSlow != nullptr || pFast != nullptr)
	{
		if (pSlow = pFast)
		{
			return pFast;  //当快指针追上了慢指针,则表示有环,且重合点即为相遇节点
		}

		pSlow = pSlow->m_pNext;
		pFast = pFast->m_pNext;
		
		if (pFast != nullptr)
		{
			pFast = pFast->m_pNext;
		}
	}
	return nullptr;
}


//找到环中的任意节点,即可以确定环中的节点数,然后找到入口节点
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
	ListNode* meetingNode = MeetingNode(pHead);
	if (meetingNode == nullptr)
	{
		return nullptr;
	}

	int count = 1;
	ListNode* pNode1 = meetingNode;
	//当从相遇节点,开始走,一边走一边计数,当再次回到相遇节点,即算出环中节点个数
	while (pNode1->m_pNext != meetingNode)
	{
		pNode1 = pNode1->m_pNext;
		count++;
	}
	//将pNode1放置头结点,然后移动环中节点数的次数,
	pNode1 = pHead;
	for (int i =0 ;i < count;i++ )
	{
		pNode1 = pNode1->m_pNext;
	}

	//第一个指针走完,第二指针和第一指针,开始正常走,直到相遇。则是入口节点,
	ListNode* pNode2 = pHead;
	while (pNode1 != pNode2)
	{
		pNode1 = pNode1->m_pNext;
		pNode2 = pNode2->m_pNext;
	}

	return pNode1;

}

测试用例

// ==================== Test Code ====================

void Test(const char *testname, ListNode* pHead, ListNode* expected)
{
	if (testname != nullptr)
	{
		printf("%s begins\n", testname);
	}
	if (EntryNodeOfLoop(pHead) == expected)
	{
		printf("PASSED!!!!\n");
	}
	else
	{
		printf("Failed!!!\n");
	}

}


//只有一个节点,没有环
void test1()
{
	ListNode* pNode1 = CreateListNode(1);

	Test("test1", pNode1, nullptr);
	DestroyList(pNode1);
}


//只有一个节点,一个环
void test2()
{
	ListNode* pNode1 = CreateListNode(1);
	ConnectListNodes(pNode1, pNode1);

	Test("TEST2", pNode1, pNode1);

	delete pNode1;
	pNode1 = nullptr;


}

//有多个节点,且有环
void test3()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode4);
	ConnectListNodes(pNode4, pNode5);
	ConnectListNodes(pNode5, pNode3);

	Test("Test3", pNode1, pNode3);

	delete pNode1;
	pNode1 = nullptr;
	delete pNode2;
	pNode2 = nullptr;
	delete pNode3;
	pNode3 = nullptr;
	delete pNode4;
	pNode4 = nullptr;
	delete pNode5;
	pNode5 = nullptr;
}

//有多个节点,且环点位于头结点
void test4()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode4);
	ConnectListNodes(pNode4, pNode5);
	ConnectListNodes(pNode5, pNode1);

	Test("Test4", pNode1, pNode1);

	delete pNode1;
	pNode1 = nullptr;
	delete pNode2;
	pNode2 = nullptr;
	delete pNode3;
	pNode3 = nullptr;
	delete pNode4;
	pNode4 = nullptr;
	delete pNode5;
	pNode5 = nullptr;
}

有多个节点,且环点位于尾结点
// A list has multiple nodes, with a loop 
void Test4()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode4);
	ConnectListNodes(pNode4, pNode5);
	ConnectListNodes(pNode5, pNode1);

	Test("Test4", pNode1, pNode1);

	delete pNode1;
	pNode1 = nullptr;
	delete pNode2;
	pNode2 = nullptr;
	delete pNode3;
	pNode3 = nullptr;
	delete pNode4;
	pNode4 = nullptr;
	delete pNode5;
	pNode5 = nullptr;
}

// A list has multiple nodes, with a loop 
void test5()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode4);
	ConnectListNodes(pNode4, pNode5);
	ConnectListNodes(pNode5, pNode5);

	Test("Test5", pNode1, pNode5);

	delete pNode1;
	pNode1 = nullptr;
	delete pNode2;
	pNode2 = nullptr;
	delete pNode3;
	pNode3 = nullptr;
	delete pNode4;
	pNode4 = nullptr;
	delete pNode5;
	pNode5 = nullptr;
}

//多个节点,且无环
void test6()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode4);
	ConnectListNodes(pNode4, pNode5);

	Test("Test6", pNode1, nullptr);

	DestroyList(pNode1);
}



int main()
{
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值