问题

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

分析

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

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

为什么呢?

(先“借”一张图

第一次相遇时,慢指针走 $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 ()
{
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 -;
node* har = head;
node* tor = head; while ()
{
if (tor->next != NULL) tor = tor->next;
else return -;
if (har->next != NULL && har->next->next != NULL) har = har->next->next;
else return -; 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[]; //enough to run our tests
for (i = ; i < sizeof(nodes) / sizeof(node); i++) {
nodes[i].next = ;
nodes[i].value = i;
}
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
printf("Checking first list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[]) ? "a" : "no");
printf("Entranc:%d\n", find_cycle_entrance(&nodes[])); nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
printf("Checking second list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[]) ? "a" : "no");
printf("Entranc:%d\n", find_cycle_entrance(&nodes[])); nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
printf("Checking third list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[]) ? "a" : "no");
printf("Entranc:%d\n", find_cycle_entrance(&nodes[])); nodes[].next = &nodes[];
printf("Checking fourth list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[]) ? "a" : "no");
printf("Entranc:%d\n", find_cycle_entrance(&nodes[])); nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
nodes[].next = &nodes[];
printf("Checking fifth list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[]) ? "a" : "no");
printf("Entranc:%d\n", find_cycle_entrance(&nodes[])); 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 ;
}

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

C语言实验1—— C中的指针和结构体的更多相关文章

  1. 【阅读笔记】《C程序员 从校园到职场》第七章 指针和结构体

    原文地址:让你提前认识软件开发(13):指针及结构体的使用 CSDN博客 https://blog.csdn.net/zhouzhaoxiong1227/article/details/2387299 ...

  2. Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

    Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...

  3. C语言--- 高级指针2(结构体指针,数组作为函数参数)

    一.结构体指针 1. 什么是结构体指针?指向结构体变量的指针     结构体:     typedef  struct stu{                          char name[ ...

  4. c语言指针与结构体

    #include <stdio.h> #include <stdlib.h> struct mydata { int num; ]; }; void main1() { /*i ...

  5. 嵌入式-C语言:通过结构体指针操作结构体内容

    #include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...

  6. 嵌入式-C语言基础:通过结构体指针访问结构体数组

    #include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...

  7. 深入理解C指针之六:指针和结构体

    原文:深入理解C指针之六:指针和结构体 C的结构体可以用来表示数据结构的元素,比如链表的节点,指针是把这些元素连接到一起的纽带. 结构体增强了数组等集合的实用性,每个结构体可以包含多个字段.如果不用结 ...

  8. 36深入理解C指针之---结构体的内存处理

    一.有关结构体的内存处理包括,结构体指针和结构体成员指针的内存分配.结构体成员的数据对齐.结构体的内存释放 1.定义:与自定义数据类型(结构体)有关的内存分配.大小和释放问题 2.特征: 1).用内存 ...

  9. C++指针和结构体基础知识

    学习C++首先要回忆起C语言当中的指针和结构体知识,本文作者将通过一段代码来总结指针和结构体基础知识:指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使 ...

随机推荐

  1. kubelet tls

    当成功签发证书后,目标节点的 kubelet 会将证书写入到 --cert-dir= 选项指定的目录中:此时如果不做其他设置应当生成上述除ca.pem以外的4个文件 kubelet-client.cr ...

  2. 3.JVM 垃圾收集器

    Garbage Collect(垃圾回收) 1.1 如何确定一个对象是垃圾? 要想进行垃圾回收,得先知道什么样的对象是垃圾. 1.1.1 引用计数法 对于某个对象而言,只要应用程序中持有该对象的引用, ...

  3. Linux07 查找文件(find、locate)

    一.一般查找:find find  PATH  -name  FILENAME 我们也可是使用 ‘*’ 通配符来模糊匹配要查找的文件名 二.数据库查找:locate locate  FILENAME ...

  4. json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (ch

    阐述 想要把一个字符串转化成字典对象,在使用json的过程出现如此报错 解决方法 将字符串里面的单引号改为双引号

  5. 19 IO流(十六)——Commons工具包,FileUtils(一)

    Commons包的API:自己查吧懒得传云 Commons包的导入方法 Commons是一个java的IO开源工具,导入方法: 从apache.org下载commons包 解压 copy其中的comm ...

  6. Find the median(线段树+离散化)(2019牛客暑期多校训练营(第七场))

    题目出处:Find the median 示例: 输入: 53 1 4 1 5 92 7 1 8 2 9 输出:3 4 5 4 5 说明:L = [3, 2 ,4, 1, 7],R = [4, 8, ...

  7. 【Linux】一步一步学Linux——Centos7.5安装图解(08)

    00. 目录 参考博客:https://mp.csdn.net/mdeditor/95031775# 01. Centos7.5简介 CentOS(Community Enterprise Opera ...

  8. 「CTS2019」珍珠

    「CTS2019」珍珠 解题思路 看了好多博客才会,问题即要求有多少种方案满足数量为奇数的变量数 \(\leq n-2m\).考虑容斥,令 \(F(k)\) 为恰好有 \(n\) 个变量数量为奇数的方 ...

  9. Disruptor分布式id生成策略

    需要的pom文件: <!-- 顺序UUID --> <dependency> <groupId>com.fasterxml.uuid</groupId> ...

  10. 5_PHP数组_3_数组处理函数及其应用_4_数组和变量间的转换函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 数组和变量间的转换函数 1. list() 语言结构 程序: <?php $info = array('co ...