有环单链表需要解决的问题:
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;
- }