有環單鏈表需要解決的問題:
1、如何判斷有環沒有環?
使用追趕的方法,設定兩個指針slow、fast,從頭指針開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。
2、如何判斷環的長度?
記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞slow所走過的操作數就是環的長度s
3、如何找到環的連接點在哪裏?
有定理:碰撞點p到連接點的距離=頭指針到連接點的距離,因此,分別從碰撞點、頭指針開始走,相遇的那個點就是連接點。
4、如何求帶環單鏈表的長度?
問題3中已經求出連接點距離頭指針的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度
- #include<iostream>
- using namespace std;
- struct Node
- {
- int data;
- Node *next;
- };
- //判斷是否有環
- Node* CircleExist(Node *head)
- {
- Node *slow=head;
- Node *fast=head;
- while(fast!=NULL&&fast->next!=NULL)
- {
- slow=slow->next;
- fast=fast->next->next;
- if(slow==fast)
- return slow;
- }
- return NULL;
- }
- //得到環的長度
- int GetCircleLength(Node *slow)
- {
- int length=1;
- Node *fast=slow;
- slow=slow->next;
- fast=fast->next->next;
- while(fast!=slow)
- {
- slow=slow->next;
- fast=fast->next->next;
- length++;
- }
- return length;
- }
- //得到環的連接點
- int GetConnectPoint(Node *head,Node *slow,int &count)
- {
- count=0;
- while(head!=slow)
- {
- head=head->next;
- slow=slow->next;
- count++;
- }
- return slow->data;
- }
- void main()
- {
- Node list[8];
- for(int i=0;i<8;i++)
- list[i].data=i;
- list[0].next=&list[1];
- list[1].next=&list[2];
- list[2].next=&list[3];
- list[3].next=&list[4];
- list[4].next=&list[5];
- list[5].next=&list[6];
- list[6].next=&list[7];
- list[7].next=&list[2];
- Node *c=CircleExist(&list[0]);
- if(c!=NULL)
- cout<<"有環!\n";
- else
- {
- cout<<"無環!\n";
- return;
- }
- int circlelength=GetCircleLength(c);
- cout<<"環的長度:"<<circlelength<<endl;
- int count=0;
- cout<<"環的連接點:"<<GetConnectPoint(&list[0],c,count)<<endl;
- cout<<"鏈表總長度:"<<count+circlelength<<endl;
- }