// 面试题23:链表中环的入口结点 // 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中, // 环的入口结点是结点3。 #include <iostream> #include "List.h" 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 (pFast != nullptr && pSlow != nullptr)//判断碰到尾节点后有没有环 { if (pFast == pSlow) 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 nodesInLoop = 1; ListNode* pNode1 = meetingNode; while (pNode1->m_pNext != meetingNode) { pNode1 = pNode1->m_pNext; ++nodesInLoop; } // 先移动pNode1,次数为环中结点的数目 pNode1 = pHead; for (int i = 0; i < nodesInLoop; ++i) pNode1 = pNode1->m_pNext; // 再移动pNode1和pNode2 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* entryNode) { if (testName != nullptr) printf("%s begins: ", testName); if (EntryNodeOfLoop(pHead) == entryNode) printf("Passed. "); else printf("FAILED. "); } // A list has a node, without a loop void Test1() { ListNode* pNode1 = CreateListNode(1); Test("Test1", pNode1, nullptr); DestroyList(pNode1); } // A list has a node, with a loop void Test2() { ListNode* pNode1 = CreateListNode(1); ConnectListNodes(pNode1, pNode1); Test("Test2", pNode1, pNode1); delete pNode1; pNode1 = nullptr; } // A list has multiple nodes, with a loop 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; } // 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; } // A list has multiple nodes, without a loop 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); } // Empty list void Test7() { Test("Test7", nullptr, nullptr); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); system("pause"); return 0; }