检测链表中是否存在环

题目、解析和代码

题目:给定一个单链表,判断其中是否有环的存在
解析:这里使用两个遍历速度不一样的结点进行判断,一个慢结点从首结点开始遍历,这个结点每次只遍历一个结点;一个快结点从第二个结点进行遍历,一次遍历两个结点。
若是链表中存在环,那么必然在某个结点处相遇;若是没有环,那么尾结点后继指针指向空。
LinkedListChainTest.c代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct operatorNodeStruce {int data;struct operatorNodeStruce* next;
}operatorNode;int main(int argc, char *argv[]) {if(argc == 1){printf("请输入链表中结点个数和环的接连位置\n");return 0;}else if(argc == 2){printf("请输入环的接连位置,负数表示没有环\n");return 0;}else if(argc > 3){printf("参数不能大于3个\n");return 0;}int nodeNumber = atoi(argv[1]);int chainNodeIndex = atoi(argv[2]);if(chainNodeIndex>nodeNumber){printf("环的接连位置应该小于链表中结点个数\n");return 0;}operatorNode *head = NULL;operatorNode *storeNode = NULL;int i=1;// 创建链表,这个链表有nodeNumber个结点for(;i<=nodeNumber;i++){operatorNode *newNode = (operatorNode *)malloc(sizeof(operatorNode));newNode->next = NULL;newNode->data = i;if(head == NULL){head = newNode;storeNode = head;}else{storeNode->next = newNode;}if(storeNode -> next != NULL){storeNode = storeNode -> next;}}//把最后一个结点的后继指针next指向第chainNodeIndex个结点,这样的话才能形成环operatorNode *chainNodeBefore = NULL;operatorNode *node= NULL;if(chainNodeIndex > 0){for(int i=0;i<chainNodeIndex;i++){if(node == NULL){node = head;}chainNodeBefore = node;node = node->next;}}storeNode->next = chainNodeBefore;// 使用快慢结点法来判断是否有环,slowNode从第一个结点开始往后遍历,每次只遍历一个结点;fastNode从第二个结点开始往后遍历,每次遍历二个结点;// 要是有环,快结点(fastNode)一定能够在某个结点处跟慢结点(slowNode)相遇operatorNode *fastNode = NULL;if(head->next != NULL){fastNode = head->next;}operatorNode *slowNode = head;while(true){if(fastNode== NULL){printf("无环\n");return 0;}else if(fastNode->next == NULL){printf("无环\n");return 0;}else if(fastNode->next->next == NULL){printf("无环\n");return 0;}else{if(slowNode == fastNode){printf("有环\n");return 0;}slowNode = slowNode->next;fastNode = fastNode->next->next;}}return 0;
}

gcc LinkedListChainTest.c -o LinkedListChainTest进行编译。
在这里插入图片描述

./LinkedListChainTest 6 4表示这个链表有6个结点,最后一个结点后继指针指向第4个结点,就像下图所示。
在这里插入图片描述

./LinkedListChainTest 7 2表示这个链表有7个结点,最后一个结点后继指针指向第2个结点,就像下图所示。
在这里插入图片描述

./LinkedListChainTest 8 3表示这个链表有8个结点,最后一个结点后继指针指向第3个结点,就像下图所示。
在这里插入图片描述

遍历解析

./LinkedListChainTest 6 4为例进行解析。
在这里插入图片描述
如上图,蓝色圆心虚线箭头为慢结点(slowNode)所在位置的标识。

在这里插入图片描述
如上图,绿色实心箭头为快结点(fastNode)所在位置的标识。

刚开始的实例图如下:
在这里插入图片描述

1次遍历之后,慢结点在第2个结点处,快结点在第4个结点处:
在这里插入图片描述

2次遍历之后,慢结点在第3个结点处,快结点在第6个结点处:
在这里插入图片描述

3次遍历之后,慢结点在第4个结点处,快结点在第5个结点处:
在这里插入图片描述

4次遍历之后,慢结点在第5个结点处,快结点在第5个结点处,可以判定有环:
在这里插入图片描述

复杂度分析

结点个数环的接连位置快结点在环中所落位置遍历次数
612、4、65
623、5、2、4、64
634、63
645、4、65
6565
6665
711、3、5、7、2、4、66
722、4、65
733、5、7、4、64
744、63
755、7、65
7665
7766

若链表中有2n(n>=1,是正整数,2n为偶数)个结点:

那么若环的连接位置x不大于n,那么遍历次数为2n-x
若是环的连接位置x大于n,则最多遍历次数小于等于2n-1,还没有总结出来公式。

若链表中有2n+1(n>=1,是正整数,2n+1为偶数)个结点:

那么环的连接位置x若不大于n+1,那么遍历次数为2n+1-x
若是环的连接位置x大于n,则最多遍历次数小于等于2n+1,还没有总结出来公式。

若是没有环的话,最多遍历次数是n/2
综上所述,最好时间复杂度和最坏时间复杂度都是O(n),平均时间复杂度也是O(n)
而空间复杂度是O(1),因为除了存储变量的必要空间,没有申请额外的空间。
因为需要更好地分析时间复杂度,所以,我把代码修改成下方所示:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct operatorNodeStruce {int data;struct operatorNodeStruce* next;
}operatorNode;int main(int argc, char *argv[]) {if(argc == 1){printf("请输入链表中结点个数和环的接连位置\n");return 0;}else if(argc == 2){printf("请输入环的接连位置,负数表示没有环\n");return 0;}else if(argc > 3){printf("参数不能大于3个\n");return 0;}int nodeNumber = atoi(argv[1]);int chainNodeIndex = atoi(argv[2]);if(chainNodeIndex>nodeNumber){printf("环的接连位置应该小于链表中结点个数\n");return 0;}operatorNode *head = NULL;operatorNode *storeNode = NULL;int i=1;// 创建链表,这个链表有nodeNumber个结点for(;i<=nodeNumber;i++){operatorNode *newNode = (operatorNode *)malloc(sizeof(operatorNode));newNode->next = NULL;newNode->data = i;if(head == NULL){head = newNode;storeNode = head;}else{storeNode->next = newNode;}if(storeNode -> next != NULL){storeNode = storeNode -> next;}}//把最后一个结点的后继指针next指向第chainNodeIndex个结点,这样的话才能形成环operatorNode *chainNodeBefore = NULL;operatorNode *node= NULL;if(chainNodeIndex > 0){for(int i=0;i<chainNodeIndex;i++){if(node == NULL){node = head;}chainNodeBefore = node;node = node->next;}}storeNode->next = chainNodeBefore;// 使用快慢结点法来判断是否有环,slowNode从第一个结点开始往后遍历,每次只遍历一个结点;fastNode从第二个结点开始往后遍历,每次遍历二个结点;// 要是有环,快结点(fastNode)一定能够在某个结点处跟慢结点(slowNode)相遇operatorNode *fastNode = NULL;if(head->next != NULL){fastNode = head->next;}operatorNode *slowNode = head;int chainNodetimes = 0;while(true){if(chainNodetimes != 0){printf("fastNode data:%d\tslowNode data: %d\n",fastNode->data,slowNode->data);}if(fastNode== NULL){printf("无环\n");return 0;}else if(fastNode->next == NULL){printf("无环\n");return 0;}else if(fastNode->next->next == NULL){printf("无环\n");return 0;}else{if(slowNode == fastNode){printf("循环次数:%d\n",chainNodetimes);printf("有环\n");return 0;}slowNode = slowNode->next;fastNode = fastNode->next->next;chainNodetimes++;}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/55586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

交通科技与管理杂志社交通科技与管理编辑部2023年第9期目录

专家论坛 黑龙江省经济高质量发展与生态环境保护耦合协调发展研究 刘降斌;祃玉帅; 1-5142 我国省际数字经济高质量发展水平综合评价研究 耿娟;毕晨曦; 6-8 振兴龙江《交通科技与管理》投稿邮箱&#xff1a;cn7kantougao163.com(注明投稿“《交通科技与管理》”) 数…

首席执行官Adam Selipsky解读“亚马逊云科技的技术产品差异化”

迄今为止&#xff0c;亚马逊云科技已经参与了21世纪几乎所有的大型计算变革&#xff0c;亚马逊云科技是一个很传奇的故事&#xff0c;它始于大约20年前的一项实验&#xff0c;当时亚马逊试图出售其过剩的服务器。人们确实对此表示怀疑。为什么在线书店试图销售云服务&#xff1…

苍穹外卖总结

前言 1、软件开发流程 瀑布模型需求分析//需求规格说明书、产品原型↓ 设计 //UI设计、数据库设计、接口设计↓编码 //项目代码、单元测试↓ 测试 //测试用例、测试报告↓上线运维 //软件环境安装、配置第一阶段&#xff1a;需求分析需求规格说明书、产品原型一般来说…

React Hooks 全解:零基础入门

Hooks 的由来 你还在为该使用无状态组件&#xff08;Function&#xff09;还是有状态组件&#xff08;Class&#xff09;而烦恼吗&#xff1f; ——拥有了hooks&#xff0c;你再也不需要写Class了&#xff0c;你的所有组件都将是Function。 你还在为搞不清使用哪个生命周期钩…

Linux: 使用 ssh 连接其他服务器

通过ifconfig 查看要连接的服务器地址&#xff1a; ubuntuubuntu1804-0172:/media/sangfor/vdc$ ssh ubuntu192.168.11.49 输入要连接的服务器密码: ubuntua192.168.1149 s password: 连接服务器成功&#xff1a;

HRS--人力资源系统(Springboot+vue)--打基础升级--(六)分页查询 + 重置按钮

一&#xff1a;先弄个简单的重置按钮 1.界面设计就放在搜索框同一列的位置 2. 在点击重置按钮时&#xff0c;清空搜索框内的内容&#xff0c;同时触发一次无条件查询(这个写法有bug&#xff0c;下面会有说明) 二&#xff1a;做分页 在MyBatis中&#xff0c;有多种方法可以实现分…

Vue2-快速搭建pc端后台管理系统

一.推荐二次开发框架 vue-element-admin Star(84k)vue-antd-admin Star(3.5k) 二.vue-element-admin 官网链接:https://panjiachen.github.io/vue-element-admin-site/zh/ 我这里搭建的是基础模版vue-admin-template(推荐) # 克隆项目 git clone https://github.com/PanJi…

VBJSON报错:缺少:语句结束

项目中使用JSON库VBJSON时报错&#xff1a; 编译错误&#xff1a;缺少&#xff1a;语句结束 cJSONScript和cStringBuilder报相同的错误&#xff0c;都在第一行: VERSION 1.0 CLASS 研究了半天没啥结果&#xff0c;之前使用这个库的时候没有什么问题&#xff0c;所以判定是当前…

mysql 字符集、比较规则, 比较规则底层逻辑

字符集的级别 show variables like ‘%charecter%’&#xff1b; character_set_server 服务器级别 一般在 5.7&#xff1a; C:\ProgramData\MySQL\MySQL Server 5.7\my.ini 8.0&#xff1a; C:\ProgramData\MySQL\MySQL Server 5.7\my.ini Linux 系列 vim /etc/my.cnf chara…

基于Spark框架的新闻推荐系统的设计与实现

1.摘要 离线ALS算法,以及基于内容的推荐算法进行结合.实时计算部分,使用Spark平台上的Spark Streaming流处理技术,处理日志收集框架Flume收集的日志信息. 2.需要的技术 jieba分词工具 LDA分词处理技术 LDA(Latent Dirichlet Allocatio

【广州华锐互动】VR高校虚拟实验教学平台提供丰富的资源支持,提高教学效果

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经逐渐渗透到各个领域&#xff0c;其中包括教育。 广州华锐互动利用VR虚拟现实技术打造的VR高校虚拟实验教学平台&#xff0c;是一种新型的教学工具&#xff0c;它提供了一个在线的教学资源管理平台&#xff0c;包含教学平台、…

电阻器件的分类

电阻器的种类碳膜电阻膜式电阻器中的一种。气态碳氢化合物在高温和真空中分解&#xff0c;碳沉积在瓷棒或者瓷管上&#xff0c;形成一层结晶碳膜。改变碳膜厚度和用刻槽的方式变更碳膜的长度可以得到不同的阻值。碳膜电阻成本较低&#xff0c;电性能和稳定性较差&#xff0c;一…

【【萌新的STM32学习-18 中断的基本概念3】】

萌新的STM32学习-18 中断的基本概念3 EXTI和IO映射的关系 AFIO简介&#xff08;F1&#xff09; Alternate Function IO 复用功能IO 主要用于重映射和外部中断映射配置 1.调试IO配置 来自AFIO_MAPR[26:24] , 配置JTAG/SWD的开关状态 &#xff08;这个我们并不用太过深刻的关注&…

Flutter 状态管理引子

1、为了更好地了解状态管理&#xff0c;先看看什么是状态。 在类似Flutter这样的响应式编程框架中&#xff0c;我们可以认为U相关的开发就是对数据进行封装&#xff0c;将之转换为具体的U1布局或者组件。借用Flutter官网的一张图&#xff0c;可以把我们在第二部分做的所有开发…

Go并发可视化解释 - Select语句

昨天&#xff0c;我发布了一篇文章&#xff0c;用可视化的方式解释了Golang中通道&#xff08;Channel&#xff09;的工作原理。如果你对通道的理解仍然存在困难&#xff0c;最好呢请在阅读本文之前先查看那篇文章。作为一个快速的复习&#xff1a;Partier、Candier 和 Stringe…

启动metastore服务报错

启动Metastore的时候报错&#xff1a; 简略的报错信息&#xff1a; MetaException(message:Error creating transactional connection factory)Caused by: MetaException(message:Error creating transactional connection factory)Caused by: javax.jdo.JDOFatalInternalExce…

数据结构(Java实现)-ArrayList与顺序表

什么是List List是一个接口&#xff0c;继承自Collection。 List的使用 List是个接口&#xff0c;并不能直接用来实例化。 如果要使用&#xff0c;必须去实例化List的实现类。在集合框架中&#xff0c;ArrayList和LinkedList都实现了List接口。 线性表 线性表&#xff08;lin…

0821|C++day1 初步认识C++

一、思维导图 二、知识点回顾 【1】QT软件的使用 1&#xff09;创建文件 创建文件时&#xff0c;文件的路径一定是全英文 2&#xff09;修改编码 工具--->选项--->行为--->默认编码&#xff1a;system 【2】C和C的区别 C又叫C plus plus&#xff0c;C是对C的扩充&…

Ubuntu18.04 交叉编译curl-7.61.0

下载 官方网址是&#xff1a;curl 安装依赖库 如果需要curl支持https协议&#xff0c;需要先交叉编译 openssl,编译流程如下&#xff1a; Ubuntu18.04 交叉编译openssl-1.1.1_我是谁&#xff1f;&#xff1f;的博客-CSDN博客 解压 # 解压&#xff1a; $tar -xzvf curl-7.61.…