快慢指針的妙用

  • 2022 年 1 月 31 日
  • 筆記

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:

關於快慢指針還有幾種比較好的演算法,希望讀者根據以上三種演算法獨立進行探索!