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 ()
{
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中的指针和结构体的更多相关文章
- 【阅读笔记】《C程序员 从校园到职场》第七章 指针和结构体
原文地址:让你提前认识软件开发(13):指针及结构体的使用 CSDN博客 https://blog.csdn.net/zhouzhaoxiong1227/article/details/2387299 ...
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...
- C语言--- 高级指针2(结构体指针,数组作为函数参数)
一.结构体指针 1. 什么是结构体指针?指向结构体变量的指针 结构体: typedef struct stu{ char name[ ...
- c语言指针与结构体
#include <stdio.h> #include <stdlib.h> struct mydata { int num; ]; }; void main1() { /*i ...
- 嵌入式-C语言:通过结构体指针操作结构体内容
#include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...
- 嵌入式-C语言基础:通过结构体指针访问结构体数组
#include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...
- 深入理解C指针之六:指针和结构体
原文:深入理解C指针之六:指针和结构体 C的结构体可以用来表示数据结构的元素,比如链表的节点,指针是把这些元素连接到一起的纽带. 结构体增强了数组等集合的实用性,每个结构体可以包含多个字段.如果不用结 ...
- 36深入理解C指针之---结构体的内存处理
一.有关结构体的内存处理包括,结构体指针和结构体成员指针的内存分配.结构体成员的数据对齐.结构体的内存释放 1.定义:与自定义数据类型(结构体)有关的内存分配.大小和释放问题 2.特征: 1).用内存 ...
- C++指针和结构体基础知识
学习C++首先要回忆起C语言当中的指针和结构体知识,本文作者将通过一段代码来总结指针和结构体基础知识:指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使 ...
随机推荐
- java接入微信JS-SDK
在微信公众号开发中不可,jssdk的接入虽然不是必须,但是根据业务需求我们还是可能用到,下面是自己整理的关于java接入的jssdk的方法,这里是记录关于接入微信JS-SDK的准备工作,关于接入JS- ...
- Testbench编写技巧
一.基本架构(常用模板) `timescale 1ns/1ps //时间精度 `define Clock //时钟周期 module my_design_tb; //================= ...
- 协议——UART(RS232)
一.UART简介 UART(universal asynchronous receiver-transmitter)是一种采用异步串行通信方式的通用异步收发传输器.一般来说,UART总是和RS232成 ...
- Mysql中HAVING的相关使用方法
having字句可以让我们筛选分组之后的各种数据,where字句在聚合前先筛选记录,也就是说作用在group by和having字句前. 而having子句在聚合后对组记录进行筛选.我的理解就是真实表 ...
- The Day Two 找到一个具有最大和的连续子数组,返回其最大和
""" 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5, ...
- JDK8-lambda表达式以及接口可以定义默认方法
一.Lambda表达式 1.Lamdba Lambda 允许把函数作为一个方法的参数,使用Lamdba可以让开发的代码更加简洁,但是易读性差,新人不了解Lamdba表达式或者代码功底有点差,不容易读懂 ...
- Sql Server 使用游标辅助循环
项目临时表#TMPxmdt 存有ID,起始年度,完成年度(int型)两个字段: 实现功能:将#TMPxmdt表中每个ID对应的起始年度至完成年度中所有年度以(ID, ND)的形式插入另一个临时表#TM ...
- 隐马尔可夫模型(HMM)的分类
1.遍历型(ergodic model) 即每个状态都可以由任意一个状态演变而来,aij>0,for all i , j. 如图: 2.left-right type of HMM 每个状态只能 ...
- 关闭 禁止 window10 UpdateOrchestrator UsoSvc服务
背景故事:w10流氓更新关了! 然后重启还更新? 读者肯定关过win10自动跟新服务 如图: 然后 还有这个流氓设置 然而微软还有一招啊! 前有win10 update 后有计划任务 powershe ...
- springboot笔记08——整合swagger2
Swagger是什么? Swagger是一个RESTFUL 接口的文档在线自动生成和功能测试的框架.利用swagger2的注解可以快速的在项目中构建Api接口文档,并且提供了测试API的功能. Spr ...