【數據結構】線性表之循環鏈表練習題(判斷單鏈表是否有環)

題目一:判斷單鏈表中是否有環

描述:
1.有環的定義:鏈表的尾結點指向了鏈表中的某個結點


兩種解決方案
【方法一】
  • 使用pq兩個指針,p總是向前走,但q每次都從頭開始走,對于每個結節點,看p走的步數是否和q一樣。如果不一樣,就存在環。如圖,當p從6走到3時,總共需要6步,此時q從頭head出發,只需要兩步就到3,步數不等,存在環。
【方法二】利用快慢指針
  • 使用pq兩個指針,p每次向前走一步,q每次向前走兩步,若在某個時候,p == q,則存在環。

代碼

第一步:創建有環單鏈表

實際上在前面單鏈表創建中有兩種整表創建的方法(頭插法和尾插法):數據結構學習-線性表之單鏈表

這里只是最后一個有所改變,讓終端結點指向第二個結點,就構成了一個環。

/**
 * 隨機產生n個元素的值,建立帶頭結點的單鏈表L(尾插法)
 */
void CreatListTail(LinkList * L, int n){
    
    LinkList p,r;
    int i;
    
    srand(time(0));                            /* 初始化隨機數種子 */
    *L = (LinkList)malloc(sizeof(Node));        /* L為整個線性表 */
    r = *L;                                   /* r為指向尾部的結點 */
    
    for (i = 0; i < n; i++) {
        
        p = (LinkList)malloc(sizeof(Node));     /* 生成新節點 */
        p->data = rand()%100 +1;               /* 隨機生成100以內的數字 */
        r->next = p;                          /* 將表尾終端結點的指針指針指向新節點 */
        r = p;                                /* 將當前的新節點定義為表尾終端結點 */
    }
    
    r->next = (*L)->next->next;                /* 尾部指向第二個結點(如果無環r->next = null) */
}
第二步:用比較步數的方法【方法一】判斷是否有環

用兩個while循環實現步數的判斷

/**
 * 比較步數的方法
 */
int HasLoop(LinkList L){
    
    LinkList cur1 = L;                         /* 定義結點cur1 */
    int pos1 = 0;                              /* cur1的步數 */
    
    while (cur1) {                             /* 結點cur1存在 */
        
        LinkList cur2 = L;                     /* 定義結點cur2 */
        int pos2 = 0;                          /* cur2的步數 */
        
        while (cur2) {                         /* 結點cur2存在 */
            
            if (cur2 == cur1) {                /* 當cur2和cur1到達相同的結點時 */
                
                if (pos1 == pos2)              /* cur2和cur1走過的步數一樣,說明沒有環 */
                    break;
                else{                          /* 有環并返回1*/
                    printf("環的位置在第%d個結點處.\n\n",pos2);
                    return 1;
                }

            }
            cur2 = cur2->next;                 /* 若果沒有環,繼續下一個結點 */
            pos2++;                            /* cur2的步數自增 */
        }
        cur1 = cur1->next;                     /* cur1繼續向后一個結點 */
        pos1++;                                /* cur1的步數自增 */
    }
    return 0;
}
第三部:用快慢指針【方法二】

快慢指針在很多地方都有用到,前面一篇單鏈表練習題中也用過用快慢指針尋找中間節點

/**
 * 用快慢指針的方法
 */
int HasLoop2(LinkList L){

    LinkList p = L;
    LinkList q = L;
    
    while (p != NULL && q != NULL && q->next != NULL) {
        
        p = p->next;                          /* p每次走一步*/
        
        if (q->next != NULL) {
            q = q->next->next;                /* p每次走兩步*/
        }
        
        printf("p:%d, q:%d \n", p->data,q->data);
        
        if (p == q) {
            return 1;                        /* 當p和q相等,則表示有環 */
        }
    }
    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本文內容取自于小甲魚的數據結構與算法。http://www.lxweimin.com/p/230e6fde9c75 ...
    阿阿阿阿毛閱讀 2,929評論 0 7
  • 大學的時候不好好學習,老師在講臺上講課,自己在以為老師看不到的座位看小說,現在用到了老師講的知識,只能自己看書查資...
    和玨貓閱讀 1,482評論 1 3
  • 1.線性表的定義 線性表:零個或多個數據元素的有限序列序列:也就是說元素之間是有順序的,若元素存在多個,則第一個元...
    e40c669177be閱讀 2,094評論 6 15
  • 完整代碼需結合前面一篇順序表數據結構學習-線性表之順序表各種操作網易云課堂小甲魚課程鏈接:數據結構與算法 線性表的...
    NotFunGuy閱讀 9,297評論 0 9
  • 在上一篇文章中我們簡單說了數據結構的概念和數據結構與算法的一些關系,這一篇文章的內容是關于線性表的東西,主要有線性...
    硅谷小蝦米閱讀 1,298評論 1 3