数据结构--链表--单链表中环的检测,环的入口,环的长度的计算
生活随笔
收集整理的這篇文章主要介紹了
数据结构--链表--单链表中环的检测,环的入口,环的长度的计算
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
就如數字6一樣的單鏈表結構,如何檢測是否有6下部的○呢,并且求交叉點位置
思路
使用快慢指針(一個一次走2步,一個走1步),若快慢指針第一次相遇,則有環
慢指針路程 s=a+bs = a+bs=a+b
快指針路程 2s=a+b+n?R2s = a+b+n*R2s=a+b+n?R
s=n?Rs = n*Rs=n?R
鏈表的長度 L=a+b+c=n?R+cL = a+b+c = n*R+cL=a+b+c=n?R+c
又 L=a+RL = a + RL=a+R
則 n?R+c=a+R?(n?1)?R+c=an*R+c = a+R \Rightarrow (n-1)*R+c = an?R+c=a+R?(n?1)?R+c=a
意味著從head開始走到入口 aaa 步 == 從第一次相遇點走 n?1n-1n?1 圈 + 再走 ccc 步
由上可以使快慢指針第一次到達相遇點時,使慢指針回到head,快指針仍在相遇點,然后兩人步伐一致,最后會在入口相見。
C++代碼實現:
完整代碼見:https://github.com/hitskyer/course/tree/master/dataAlgorithm/chenmingming/linkedList
類實現函數
bool SingleList::hasLoop() {bool loop = false;ListNode fast = m_pHead, slow = m_pHead;ListNode posMeet = m_pHead, ringEntrance = m_pHead;//環的可能的入口應初始化成headif(m_pHead == NULL){loop = false;std::cout << "list has no loop!" << std::endl;}else{while(fast && fast->pNext){fast = fast->pNext->pNext;slow = slow->pNext;if(fast == slow){loop = true;posMeet = fast; //第一次相遇的地方break;}}slow = m_pHead; //接著讓慢指針回到表頭(這里是關鍵),繼續一起同步前行,第二次相遇的地方為環的入口while(slow != fast){slow = slow->pNext;fast = fast->pNext;if(fast == slow)ringEntrance = fast;}size_t lenOf_headToEntrance = howManyNode(m_pHead,ringEntrance);size_t ringLen_1 = howManyNode(ringEntrance->pNext, ringEntrance);std::cout << "len of head to ring entrance is " << lenOf_headToEntrance << std::endl;std::cout << "entrance Node is " << ringEntrance->data << std::endl;std::cout << "len of ring is " << ringLen_1 + 1 << std::endl;std::cout << "len of List is " << lenOf_headToEntrance + ringLen_1 + 1 << std::endl;}return loop; }size_t SingleList::howManyNode(ListNode ps, ListNode pe) //計算兩個指針之間有多少個節點(不包含第二個參數處的節點) {size_t count = 0;while(ps != pe){ps = ps->pNext;++count;}return count; }singleListIsLoop.cpp主函數
// // Created by mingm on 2019/3/24. //檢查單鏈表中是否存在環,求環的長度,鏈表長度,及環的入口 #include <iostream> #include <time.h> #include <cstdlib> #include "./homework/singleList.cpp" using namespace std; int main() {srand((unsigned)time(NULL)); //用時間隨機數種子size_t len = 10; //測試鏈表最大長度for(size_t j = 1; j < len; ++j){SingleList intList;for(size_t i = 0; i < j; ++i){intList.AddTail(rand()%100); //添加隨機數到鏈表}cout << "no loop list: " << endl;intList.PrintList(); //排序前鏈表打印size_t n = rand()%(intList.GetLength()); //0-鏈表減1的隨機數ListNode randNode = intList.GetHeadNode();for(size_t i = 0; i != n; ++i){randNode = randNode->pNext; //鏈表的一個隨機節點}ListNode originTail = intList.GetTailNode();originTail->pNext = randNode; //尾節點接入鏈表中的隨機位置形成環intList.hasLoop(); //調用環檢測函數originTail->pNext = NULL; //斷開環,讓鏈表能夠按照單鏈表析構函數析構!!!!!!!std::cout << "getListLength() is " << intList.GetLength() << std::endl;std::cout << "-----------------------------------------" << std::endl;}return 0; }Valgrind檢測結果
從鏈表長度1開始測試到9,測試結果均正確!
總結
以上是生活随笔為你收集整理的数据结构--链表--单链表中环的检测,环的入口,环的长度的计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样切换git账号密码错误_git中多账
- 下一篇: slice 转byte go_一文告诉你