C语言如何判断链表里是否有环
创作时间:
作者:
@小白创作中心
C语言如何判断链表里是否有环
引用
1
来源
1.
https://docs.pingcode.com/baike/1208193
在C语言中,判断链表是否有环是一个常见的编程问题。本文将介绍三种常用的方法:快慢指针法、哈希表法和修改链表结构法,并通过详细的步骤说明和示例代码帮助读者理解这些方法的实现原理。
快慢指针法
快慢指针法,也称为龟兔赛跑算法,是判断链表中是否存在环的经典方法。其核心思想是利用两个指针以不同的速度遍历链表。
具体步骤
- 初始化两个指针:慢指针(slow)和快指针(fast),都指向链表的头节点。
- 在链表中进行遍历:
- 慢指针每次移动一个节点。
- 快指针每次移动两个节点。
- 如果快指针与慢指针相遇,则说明链表中存在环。
- 如果快指针移动到链表的末尾(即指向 NULL),则说明链表中没有环。
示例代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
};
int hasCycle(struct ListNode *head) {
struct ListNode *slow = head;
struct ListNode *fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return 1; // 有环
}
}
return 0; // 无环
}
int main() {
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = 1;
head->next = head; // 创建一个有环的链表
int result = hasCycle(head);
if (result) {
printf("链表中有环\n");
} else {
printf("链表中无环\n");
}
free(head);
return 0;
}
哈希表法
哈希表法利用哈希表来存储已访问的节点地址,从而检测链表中是否存在环。这种方法的时间复杂度为O(n),但需要额外的空间来存储节点地址。
具体步骤
- 初始化一个哈希表。
- 遍历链表中的每个节点:
- 如果节点的地址已经存在于哈希表中,则说明链表中存在环。
- 如果节点的地址不在哈希表中,则将该节点地址存入哈希表。
- 如果遍历结束后没有发现重复的节点地址,则说明链表中没有环。
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <uthash.h>
struct ListNode {
int val;
struct ListNode *next;
};
struct HashNode {
struct ListNode *key;
UT_hash_handle hh;
};
int hasCycle(struct ListNode *head) {
struct HashNode *visited = NULL, *tmp;
while (head != NULL) {
HASH_FIND_PTR(visited, &head, tmp);
if (tmp != NULL) {
return 1; // 有环
}
tmp = (struct HashNode*)malloc(sizeof(struct HashNode));
tmp->key = head;
HASH_ADD_PTR(visited, key, tmp);
head = head->next;
}
// 释放哈希表
HASH_ITER(hh, visited, tmp, tmp) {
HASH_DEL(visited, tmp);
free(tmp);
}
return 0; // 无环
}
int main() {
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = 1;
head->next = head; // 创建一个有环的链表
int result = hasCycle(head);
if (result) {
printf("链表中有环\n");
} else {
printf("链表中无环\n");
}
free(head);
return 0;
}
修改链表结构法
修改链表结构法通过修改链表节点的结构来标记已访问的节点,从而判断链表中是否存在环。这种方法需要修改链表节点的结构,不适用于所有场景。
具体步骤
- 在链表节点结构中添加一个标记位。
- 遍历链表中的每个节点:
- 如果节点的标记位已被标记,则说明链表中存在环。
- 如果节点的标记位未被标记,则标记该节点。
- 如果遍历结束后没有发现已标记的节点,则说明链表中没有环。
示例代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
int visited; // 新增的标记位
};
int hasCycle(struct ListNode *head) {
while (head != NULL) {
if (head->visited) {
return 1; // 有环
}
head->visited = 1;
head = head->next;
}
return 0; // 无环
}
int main() {
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = 1;
head->next = head; // 创建一个有环的链表
head->visited = 0;
int result = hasCycle(head);
if (result) {
printf("链表中有环\n");
} else {
printf("链表中无环\n");
}
free(head);
return 0;
}
总结
在C语言中,判断链表是否有环的常用方法包括快慢指针法、哈希表法、修改链表结构法。其中,快慢指针法是最常用和最有效的方法,因为它不需要额外的空间,只需要两个指针即可实现。哈希表法虽然简单直接,但需要额外的空间来存储节点地址。而修改链表结构法则需要修改节点结构,不适用于所有场景。
无论选择哪种方法,都需要根据具体的应用场景和要求来决定。对于大多数情况,推荐使用快慢指针法,因为它的时间复杂度为O(n),且不需要额外的空间。对于需要精确检测和存储已访问节点的情况,可以考虑使用哈希表法。修改链表结构法虽然简单,但不推荐在实际应用中使用,除非可以确保链表节点结构可以被修改。
此外,在实际开发过程中,使用合适的项目管理系统可以提高开发效率和项目管理的质量。推荐使用研发项目管理系统PingCode和通用项目管理软件Worktile,它们可以帮助团队更好地管理和跟踪项目进度,提高开发效率和项目质量。
通过合理选择和应用这些方法,可以有效地判断链表中是否存在环,从而提高程序的健壮性和可靠性。
热门推荐
二项式定理:从基础到广义应用
凤凰花的象征意义及其在中国文化中的传统应用
走进冒菜世界:多样食材与独特风味交织,味蕾的狂欢派对
《哪吒之魔童降世》:叛逆魔童的逆天之旅
中控系统操作手册与日常维护
川味干锅肥肠的家常做法
国网能源院发布《中国电力供需分析报告2024》
养老金融产品老年人投资服务方案
搭配小心机之蝴蝶结,宋茜、江疏影等明星都在用它演绎少女范
缎带编织蝴蝶结的手工教程
柜门一般多宽,选择柜门宽度时的考虑因素
传染性单核细胞增多症又叫什么
数字技术如何颠覆体育产业?从机遇到挑战的深度解读
“一生痴绝处,无梦到徽州” 背后的真实故事
强留员工加班,真能提高工作效益吗?福特公司:加班有损企业利益
亚麻籽改善便秘的作用
《西游记》中的友情与团队精神
红薯淀粉加工产量不高是什么原因?怎么提高红薯淀粉产量?
方孝孺宁死不屈:对忠诚与气节的坚守
民国定都南京的原因是什么?背后的历史背景有哪些?
工业自动化中的五大核心测量参数,你掌握了吗?
如何为Logo选择合适的品牌色?聊聊其中的色彩心理学
梦见戴着金戒指的预兆
装修公司 | 打孔、开槽、绕梁?看看哪种横梁布管方式适合你家?
过敏性鼻炎患者的饮食调理指南:远离过敏,健康呼吸
一味中药是虫子脱下的壳,能够清热利咽,对眼睛、惊厥、皮疹效果很好哦~
一味中药是虫子脱下的壳,能够清热利咽,对眼睛、惊厥、皮疹效果很好哦~
什么面条营养价值高(5种营养师推荐的健康面条)
BMJ:笑能救干眼症!中山团队试验表明,笑声锻炼改善干眼症效果比人工泪液还好
如何合理设置技术分析指标参数?这类参数设置如何适应不同的市场行情?