题目:
判断给定的一个链表中是否存在环。
解题思路:
1、初始化两个指针,slow 和 fast,都指向链表的头节点。
2、进入循环,每次循环中:
slow 指针向前移动一步。
fast 指针向前移动两步。
3、检查 slow 和 fast 是否相遇:
如果相遇,则链表中存在环,返回 true。
如果 fast 或 fast->next 到达链表的末尾(即指向 NULL),则链表中不存在环,返回 false。
举例分析:
构造带环链表:
假设有一个链表,其节点编号依次为1,2,3,4。人为制造一个环,让节点4的 next 指针指向节点2。这样,链表中就形成了一个环,其中环的起点是节点2,经过节点3,到达节点 4,然后又回到节点2。
快慢指针判断:
初始化指针:
慢指针(slow):指向链表的头节点,即节点1。
快指针(fast):指向链表的头节点,即节点1。
移动指针规则:
慢指针每次移动一步,即 slow = slow->next。
快指针每次移动两步,即 fast = fast->next->next。
指针移动过程:
第一步:慢指针指向节点2,快指针指向节点3。
第二步:慢指针指向节点3,快指针指向节点2。
第三步:慢指针指向节点4,快指针指向节点4。(相遇)
判断结果:
如果快指针和慢指针相遇,那么链表中存在环。如果快指针到达链表的末尾(即 fast == NULL 或 fast->next == NULL),那么链表中不存在环。
程序代码:
cpp
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct ListNode {
int val; //数据域
struct ListNode *next; //指针域
} ListNode;
// 创建新节点
ListNode* createNode(int val) {
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
newNode->val = val;
newNode->next = NULL;
return newNode;
}
// 判断链表中是否有环
int hasCycle(ListNode *head) {
if (head == NULL || head->next == NULL) {//当为空或者只有一个节点时,直接返回
return 0;
}
ListNode *slow = head;
ListNode *fast = head;
while (slow != fast) { //在快指针到NULL时都没有与慢指针相遇
if (fast == NULL || fast->next == NULL) {
return 0; // 链表无环
}
slow = slow->next;
fast = fast->next->next;
}
return 1; // 链表有环
}
// 测试
int main() {
ListNode* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(3);
head->next->next->next = head->next; // 创建环
if (hasCycle(head)) {
printf("链表中有环\n");
} else {
printf("链表中无环\n");
}
// 释放内存
free(head->next->next);
free(head->next);
free(head);
head = NULL;
return 0;
}