C语言实验1—— C中的指针和结构体

问题

实现一个算法,检测单链表中是否有环,如果有环还要得到环的入口。

分析

判断是否有环:快慢指针法(也叫“龟兔赛跑”),慢指针每次移动一位,快指针每次移动两位,如果有环,他们一定会相遇。

求环的入口:到达相遇的位置时,将块指针移动到头指针的位置,每次移动一位,两者再次相遇的位置就是环的入口。

为什么呢?

(先“借”一张图

 

 第一次相遇时,慢指针走 $x+k$,快指针走 $x+k+mr$($r$ 为环的长度, $m \geq 1$),

又因为快指针的速度是慢指针的两倍,所以 $2(x+k) = x+k+mr$.

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

慢指针已在 $k$ 处,块指针置0,还过 $x$ 步,它们就会相遇于环的入口。

#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;
}

 

 

参考链接:https://blog.csdn.net/qq_36781505/article/details/91401474

posted @ 2019-09-04 17:23  Rogn  阅读(611)  评论(0编辑  收藏  举报