C語言實驗1—— C中的指針和結構體

問題

實現一個算法,檢測單鏈表中是否有環,若是有環還要獲得環的入口。node

分析

判斷是否有環:快慢指針法(也叫「龜兔賽跑」),慢指針每次移動一位,快指針每次移動兩位,若是有環,他們必定會相遇。算法

求環的入口:到達相遇的位置時,將塊指針移動到頭指針的位置,每次移動一位,二者再次相遇的位置就是環的入口。spa

爲何呢?.net

(先「借」一張圖指針

 

 第一次相遇時,慢指針走 $x+k$,快指針走 $x+k+mr$($r$ 爲環的長度, $m \geq 1$),code

又由於快指針的速度是慢指針的兩倍,因此 $2(x+k) = x+k+mr$.blog

即 $x = mr-k$($m \geq 1$),get

慢指針已在 $k$ 處,塊指針置0,還過 $x$ 步,它們就會相遇於環的入口。it

#include <stdio.h>
#include<stdbool.h>

typedef struct node {
    int value;
    struct node *next;
} node;

bool ll_has_cycle(node *head) {
    if (head == NULL)  return false;
    node* har = head;
    node* tor = head;

    while (1)
    {
        if (tor->next != NULL)  tor = tor->next;
        else   return false;
        if (har->next != NULL && har->next->next != NULL)  har = har->next->next;
        else  return false;

        if (tor == har)  return true;
    }
}

int find_cycle_entrance(node *head) {
    if (head == NULL)  return -1;
    node* har = head;
    node* tor = head;

    while (1)
    {
        if (tor->next != NULL)  tor = tor->next;
        else   return -1;
        if (har->next != NULL && har->next->next != NULL)  har = har->next->next;
        else  return -1;

        if (tor == har)
        {
            har = head;
            while(har != tor)
            {
                har = har->next;
                tor = tor->next;
            }
            return har->value;
        }
    }
}

void test_ll_has_cycle(void) {
    int i;
    node nodes[25]; //enough to run our tests
    for (i = 0; i < sizeof(nodes) / sizeof(node); i++) {
        nodes[i].next = 0;
        nodes[i].value = i;
    }
    nodes[0].next = &nodes[1];
    nodes[1].next = &nodes[2];
    nodes[2].next = &nodes[3];
    printf("Checking first list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[0]) ? "a" : "no");
     printf("Entranc:%d\n", find_cycle_entrance(&nodes[0]));

    nodes[4].next = &nodes[5];
    nodes[5].next = &nodes[6];
    nodes[6].next = &nodes[7];
    nodes[7].next = &nodes[8];
    nodes[8].next = &nodes[9];
    nodes[9].next = &nodes[10];
    nodes[10].next = &nodes[4];
    printf("Checking second list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[4]) ? "a" : "no");
    printf("Entranc:%d\n", find_cycle_entrance(&nodes[4]));

    nodes[11].next = &nodes[12];
    nodes[12].next = &nodes[13];
    nodes[13].next = &nodes[14];
    nodes[14].next = &nodes[15];
    nodes[15].next = &nodes[16];
    nodes[16].next = &nodes[17];
    nodes[17].next = &nodes[14];
    printf("Checking third list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[11]) ? "a" : "no");
    printf("Entranc:%d\n", find_cycle_entrance(&nodes[11]));

    nodes[18].next = &nodes[18];
    printf("Checking fourth list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[18]) ? "a" : "no");
    printf("Entranc:%d\n", find_cycle_entrance(&nodes[18]));

    nodes[19].next = &nodes[20];
    nodes[20].next = &nodes[21];
    nodes[21].next = &nodes[22];
    nodes[22].next = &nodes[23];
    printf("Checking fifth list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[19]) ? "a" : "no");
    printf("Entranc:%d\n", find_cycle_entrance(&nodes[19]));

    printf("Checking length-zero list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(NULL) ? "a" : "no");
    printf("Entranc:%d\n", find_cycle_entrance(NULL));
}

int main() {
    test_ll_has_cycle();
    return 0;
}

 

 

參考連接:http://www.javashuo.com/article/p-clcngkgp-kv.htmlio

相關文章
相關標籤/搜索