问题

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

分析

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

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

为什么呢?

(先“借”一张图

第一次相遇时,慢指针走 $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. [转帖]关于一个 websocket 多节点分布式问题的头条前端面试题

    关于一个 websocket 多节点分布式问题的头条前端面试题 https://juejin.im/post/5dcb5372518825352f524614 你来说说 websocket 有什么用? ...

  2. 【转帖】AMD Zen之父、Intel副总Jim Keller到底有多牛?

    AMD Zen之父.Intel副总Jim Keller到底有多牛? https://www.cnbeta.com/articles/tech/907295.htm 几乎玩过 所有的中国国产化CPU的祖 ...

  3. 《.NETer提高效率——环境部署》

    初衷 兵马未动,粮草先行. 电脑坏了or换工作等需要重装系统. 开发运维一把梭. 与时俱进. 记忆力差,需要文字记录. 因为懒... 目的 通过学习 Linux+docker+kubernetes+C ...

  4. 【CF1095F】 Make It Connected(最小生成树)

    题目链接 如果没有特殊边的话显然答案就是权值最小的点向其他所有点连边. 所以把特殊边和权值最小的点向其他点连的边丢一起跑最小生成树就行了. #include <cstdio> #inclu ...

  5. OpenJML入门

    目录 OpenJML 获取 下载 使用 Linux Windows Parsing and Type-checking Extended Static Checking Runtime Asserti ...

  6. C# 利用特性(Attribute)实现通用实体类数据合法校验

    用过asp.net mvc 的都应该知道,在实体类上添加一些特性,可以实现后端实体的数据校验,这里简单实现一下 实现原理:利用反射获取实体的每一个属性,并通过属性获取属性上标注的特性,调用特性的Val ...

  7. HDFS-SecondaryNameNode(SNN)角色介绍

    它出现在Hadoop1.x版本中,又称辅助NameNode,在Hadoop2.x以后的版本中此角色消失.如果充当datanode节点的一台机器宕机或者损害,其数据不会丢失,因为备份数据还存在于其他的d ...

  8. Wireshark 分析Linux SSh 远程登录延迟问题

    1.PuTTy远程登录延迟的分析 现象问题描述:在使用kali linux 的时候喜欢在后台运行而在Windows主机系统上安装PuTTY来实现远程登录 发现每次输入密码的时候会存在延迟10s的情况, ...

  9. HTML&CSS基础-样式的继承

    HTML&CSS基础-样式的继承 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML源代码 <!DOCTYPE html> <html> & ...

  10. asp.net core 读取Appsettings.json 配置文件

    Appsettingsjson 配置定义实体在StartUp时读取配置信息修改你的Controller通过构造函数进入配置信息总结Appsettings.json 配置很明显这个配置文件就是一个jso ...