循环链表创建与环起点查找实现问题咨询
解决循环链表环起点查找及链表构建问题
嘿,看起来你在手动构建带环链表时碰到了「函数内输出正常,但main调用后出问题」的情况,还要实现环起点的查找——我来帮你把这些问题理顺,一步步解决。
一、先搞定带环链表的正确构建
你提到创建链表的函数里cout head->data能输出正确值,但main里调用后出问题,大概率是链表头指针没有正确返回或者构建过程中指针处理出错了。这里给你一个靠谱的构建实现,顺便避开常见坑:
完整构建函数示例
#include <iostream> using namespace std; // 定义链表节点结构 struct ListNode { int data; ListNode* next; ListNode(int val) : data(val), next(nullptr) {} }; // 构建带环链表:参数为链表长度、环起点的位置(从1开始计数) ListNode* createCyclicList(int length, int cyclePos) { if (length <= 0) return nullptr; // 创建头节点 ListNode* head = new ListNode(1); ListNode* current = head; ListNode* cycleStart = nullptr; // 遍历创建后续节点 for (int i = 2; i <= length; ++i) { current->next = new ListNode(i); current = current->next; // 记录环的起点节点 if (i == cyclePos) { cycleStart = current; } } // 让尾节点指向环起点,形成环;如果没指定合法环位置,默认指向头节点 current->next = (cyclePos >=1 && cyclePos <= length) ? cycleStart : head; // 函数内测试输出 cout << "函数内head节点值:" << head->data << endl; return head; }
构建时要注意的点
- 必须返回头指针:如果你的构建函数是
void类型,main里根本拿不到正确的链表头,这是最容易犯的错误; - 环起点要准确记录:遍历节点时要把指定位置的指针存下来,最后让尾节点指向它,不能随便乱指;
- 输入合法性检查:要确保用户输入的环位置在1到链表长度之间,避免出现无效环。
二、环起点的查找:用经典的快慢指针法
搞定链表构建后,查找环起点用Floyd判圈算法(快慢指针)最高效,时间复杂度O(n),空间复杂度O(1)。
实现代码
// 查找环的起点 ListNode* findCycleStart(ListNode* head) { // 空链表或只有一个节点,直接返回空 if (!head || !head->next) return nullptr; ListNode* slow = head; ListNode* fast = head; // 第一步:快慢指针移动,判断是否有环 while (fast && fast->next) { slow = slow->next; fast = fast->next->next; // 相遇说明有环,跳出循环 if (slow == fast) break; } // 如果fast走到尽头,说明无环 if (!fast || !fast->next) return nullptr; // 第二步:把慢指针移回头部,快慢指针同速前进,相遇点就是环起点 slow = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow; }
算法原理简单说
当快慢指针第一次相遇时,快指针走的路程是慢指针的2倍。设链表头到环起点的距离为a,环起点到相遇点的距离为b,环长度为c,可以推导出:a = k*c - b(k是快指针绕环的圈数)。也就是说,从链表头到环起点的距离,等于相遇点绕环回到起点的距离。所以把慢指针移回头部,两者同速走,相遇时就是环起点。
三、main函数里的正确调用示例
int main() { int listLength, cyclePosition; cout << "输入链表长度:"; cin >> listLength; cout << "输入环起点的位置(从1开始):"; cin >> cyclePosition; // 构建带环链表 ListNode* head = createCyclicList(listLength, cyclePosition); // 测试main里的head是否正常 cout << "main函数内head节点值:" << head->data << endl; // 查找环起点 ListNode* startNode = findCycleStart(head); if (startNode) { cout << "环的起点值为:" << startNode->data << endl; } else { cout << "链表无环" << endl; } // 记得释放内存(带环链表的释放需要特殊处理,避免死循环) // 这里可以写一个辅助函数来释放,比如: // releaseCyclicList(head, startNode); return 0; }
最后提醒
如果你的main里还是拿不到正确的head,先检查构建函数的返回值是否正确——比如是不是函数里的head是局部变量但没返回,或者返回了临时指针导致野指针。另外,用完链表一定要记得释放内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Blooddy
相关产品推荐
相关产品推荐

