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语言当中的指针和结构体知识,本文作者将通过一段代码来总结指针和结构体基础知识:指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使 ...
随机推荐
- 《算法 - Lru算法》
一:概述 - LRU 用于管理缓存策略,其本身在 Linux/Redis/Mysql 中均有实现.只是实现方式不尽相同. - LRU 算法[Least recently used(最近最少使用)] - ...
- 手撕面试官系列(二):开源框架面试题Spring+SpringMVC+MyBatis
文章首发于今日头条:https://www.toutiao.com/i6712324863006081549/ 前言 跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽.切不可跟风,看 ...
- CodeForces-1152C-Neko does Maths
C. Neko does Maths time limit per test:1 second memory limit per test:256 megabytes input:standard i ...
- ultraedit 实际应用技巧
Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...
- Thread 与 ThreadLocal
@Testpublic void testThread() { Thread thread = Thread.currentThread(); System.out.println("thr ...
- Apach Shiro MD5密码加密过程(明文生成密码过程)详细解析
前言: 最近再项目当中使用的ApachShiro安全框架,对于权限和服务器资源的保护都有一个很好的管理.前期主要参考的文章有 项目中设计密码的加盐处理以及二次加密问题,跟着断点 一步步揭开Apach ...
- caffe基础入门
学的太浅,先放一个别人写的吧,等自己摸清楚回来搞搞. https://blog.csdn.net/cham_3/article/details/72141753
- java List分组和排序处理
在一些应用中,需要将List中的对象按某种情况分组或者排序处理.做个小结如下: 1. 如一个List中存放了ProductDoing对象,productDoing对象有rawTypeId 现在要求将r ...
- dubbo源码阅读之自适应扩展
自适应扩展机制 刚开始看代码,其实并不能很好地理解dubbo的自适应扩展机制的作用,我们不妨先把代码的主要逻辑过一遍,梳理一下,在了解了代码细节之后,回过头再来思考自适应扩展的作用,dubbo为什么要 ...
- jmeter进行压测的步骤
1)安装jmeter和Badboy. 2)用badboy录制脚本,保存之后直接导出. 3)用jmeter打开badboy录制的脚本,假如是有参数的话,需要写一个csv的参数化文件,在jmeter中添加 ...