1.判断是否有环
通常情况下单链表的尾节点是为NULL的,如果一个单链表存在环必然会使尾节点的指针域
存放的是其中某个节点的地址,这样就形成了环状结构.
在环中fast走两步,slow走一步,总会在某个时候,fast=slow
bool hasCycle(SLinkNode *L){ SLinkNode *p,*q; p=q=L; //如果链表中只存在一个节点或者为空链表,则没有环 if(L==NULL||L->next==NULL) return false; while(q!=NULL&&q->next!=NULL){ q=q->next->next; p=p->next; if(p==q)//快慢指针相遇则存在环 return true; } return false; }
2.找到环的入口
在确定链表存在环后,可以通过一下算法找到其入口
SLinkNode *findLoopStart(SLinkNode *L) { if(L==NULL&&L->next==NULL) return NULL; SLinkNode *slow,*fast; fast=slow=L; while(fast!=NULL&&fast->next!=NULL) { slow=slow->next; fast=fast->next->next; if(slow==fast) break; } SLinkNode *slow=L;//此时fast在相遇点,只需要将慢指针放回到起始点即可 while(slow!=fast) { slow=slow->next; fast=fast->next; } return slow; }
3:寻找中心节点
可以设置两个指针fast和slow,让fast先走两步slow走一步,当fast到达尾节点时
slow刚好到达中心节点,如图
SLinkNode *find_mid(SLinkNode *&L) { SLinkNode *p,*q,*s,*r; p=q=L; while(q!=NULL&&q->next!=NULL) { p=p->next;//p走一步 q=q->next->next;//q走两步 } return p;
tips:
关于快慢指针还有几种比较好的算法,希望读者根据以上三种算法独立进行探索!