C语言判断链表是否有环的三种方法
创作时间:
作者:
@小白创作中心
C语言判断链表是否有环的三种方法
引用
1
来源
1.
https://docs.pingcode.com/baike/1051718
C语言判断链表是否有环的方法包括:快慢指针法、标记法、哈希表法。快慢指针法是一种高效且常用的方法,通过两个指针——一个快速移动的指针(每次走两步)和一个慢速移动的指针(每次走一步),如果链表有环,这两个指针最终会相遇。本文将详细介绍这种方法,并进一步探讨其他方法及其实现。
一、快慢指针法
快慢指针法是判断链表是否有环的经典方法。其核心思想是,通过快指针和慢指针的不同步速移动来检测环的存在。
1.1 原理
快指针每次移动两步,慢指针每次移动一步。如果链表中存在环,快指针最终会追上慢指针。如果链表无环,快指针会到达链表末尾。
1.2 实现代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
};
int hasCycle(struct ListNode *head) {
if (!head || !head->next) return 0;
struct ListNode *slow = head;
struct ListNode *fast = head->next;
while (slow != fast) {
if (!fast || !fast->next) return 0;
slow = slow->next;
fast = fast->next->next;
}
return 1;
}
int main() {
// 创建一个带有环的链表进行测试
struct ListNode *head = malloc(sizeof(struct ListNode));
head->val = 1;
struct ListNode *second = malloc(sizeof(struct ListNode));
second->val = 2;
struct ListNode *third = malloc(sizeof(struct ListNode));
third->val = 3;
struct ListNode *fourth = malloc(sizeof(struct ListNode));
fourth->val = 4;
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = second; // 创建环
if (hasCycle(head)) {
printf("链表有环\n");
} else {
printf("链表无环\n");
}
// 释放内存(注意:实际项目中要小心处理环的释放问题)
free(fourth);
free(third);
free(second);
free(head);
return 0;
}
二、标记法
标记法通过在链表遍历的过程中临时修改节点指针或使用额外字段来标记已访问的节点,以判断是否出现重复访问。
2.1 原理
在遍历链表时,将已访问的节点进行标记(例如,将节点的指针指向特殊的标记值),如果再次遇到标记节点,则说明链表存在环。
2.2 实现代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
};
int hasCycle(struct ListNode *head) {
struct ListNode *marker = (struct ListNode *)0xdeadbeef; // 特殊标记
while (head) {
if (head == marker) return 1;
struct ListNode *next = head->next;
head->next = marker;
head = next;
}
return 0;
}
int main() {
// 创建一个带有环的链表进行测试
struct ListNode *head = malloc(sizeof(struct ListNode));
head->val = 1;
struct ListNode *second = malloc(sizeof(struct ListNode));
second->val = 2;
struct ListNode *third = malloc(sizeof(struct ListNode));
third->val = 3;
struct ListNode *fourth = malloc(sizeof(struct ListNode));
fourth->val = 4;
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = second; // 创建环
if (hasCycle(head)) {
printf("链表有环\n");
} else {
printf("链表无环\n");
}
// 释放内存(注意:实际项目中要小心处理环的释放问题)
free(fourth);
free(third);
free(second);
free(head);
return 0;
}
三、哈希表法
通过使用哈希表存储已访问的节点,在遍历过程中检测节点是否重复出现,以此判断链表是否有环。
3.1 原理
在遍历链表时,将每个访问的节点存入哈希表,如果遇到已存在于哈希表中的节点,则说明链表存在环。
3.2 实现代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int val;
struct ListNode *next;
struct ListNode *hashNext; // 用于哈希表的链表法解决冲突
};
#define HASH_SIZE 1024
struct ListNode *hashTable[HASH_SIZE] = {NULL};
int hashFunc(struct ListNode *node) {
return ((uintptr_t)node) % HASH_SIZE;
}
int hasCycle(struct ListNode *head) {
while (head) {
int hashIndex = hashFunc(head);
struct ListNode *current = hashTable[hashIndex];
while (current) {
if (current == head) return 1;
current = current->hashNext;
}
head->hashNext = hashTable[hashIndex];
hashTable[hashIndex] = head;
head = head->next;
}
return 0;
}
int main() {
// 创建一个带有环的链表进行测试
struct ListNode *head = malloc(sizeof(struct ListNode));
head->val = 1;
struct ListNode *second = malloc(sizeof(struct ListNode));
second->val = 2;
struct ListNode *third = malloc(sizeof(struct ListNode));
third->val = 3;
struct ListNode *fourth = malloc(sizeof(struct ListNode));
fourth->val = 4;
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = second; // 创建环
if (hasCycle(head)) {
printf("链表有环\n");
} else {
printf("链表无环\n");
}
// 释放内存(注意:实际项目中要小心处理环的释放问题)
free(fourth);
free(third);
free(second);
free(head);
return 0;
}
四、总结
在实际项目中,我们经常需要判断链表是否有环。上述三种方法各有优缺点:
- 快慢指针法:空间复杂度低,但需要理解指针的移动规律。
- 标记法:实现简单,但修改链表节点数据可能不合适。
- 哈希表法:容易理解和实现,但空间复杂度较高。
选择具体方法时,可以根据项目需求和资源限制进行选择。
希望本文对你在C语言中判断链表是否有环有所帮助。
热门推荐
川藏线成都到拉萨最经典的5条线路:经稻城亚丁、梅里雪山、羊湖
跟着“四普”游丽水:探访历史与红色印记
打卡缙云仙都与河阳古民居:丽水冬游新宠!
缙云仙都:人间仙境一日游完全攻略
《全家流放:我带着嫂夫人去逃荒!》:逆境中的亲情纠葛
《全家流放:我带着嫂夫人去逃荒!》:一部未完待续的权谋冒险佳作
怀念赵英俊:他用音乐温暖了我们的心,留下的爱无尽
探秘云南少数民族温泉文化之旅
大理&丽江:拍出高级感的旅行大片
华盛顿大学新地标:生命科学楼的设计奇迹
华盛顿大学西雅图分校:留学必打卡景点
华大VS清华:谁是你的梦校?
探访亚马逊和微软背后的学术摇篮:华盛顿大学西雅图分校
法国人为什么喜欢香水?揭开香气背后的文化秘密
创意无限!4种家庭版鹌鹑蛋料理制作指南
家常菜新花样:西红柿焖鹌鹑蛋
东川红土地&麻园集市:昆明摄影打卡胜地
昆明石林与滇池:一场自然与文化的自驾之旅
冬日昆明:从翠湖到石林的历史文化之旅
古装剧里的蝴蝶意象:从庄周梦蝶到虞书欣的蝴蝶造型
2025年春节档电影:一场视觉盛宴,一次心灵洗礼
弥勒菩萨的神秘兜率天宫传说
正月初七出生的人:命运与特殊性格的探究
宁德三大自然景观:太姥山、白云山、东壁村
冬游绍兴兜率天宫:探秘云顶仙境
探秘绍兴鲁迅故里,穿越时空的文化之旅
杨昶镜头下的荔波:捕捉最美瞬间
荔波夏季漂流攻略:清凉一夏!
荔波茂兰保护区:生态旅游新典范
荔波小七孔:秋冬打卡胜地,你去过吗?