目录
- 前言
- 我的思路
- 思路一 (哈希表记录链表的访问):
- 思路二 (双指针,快指针在前,慢指针在后):
- 我的代码
- 运行结果
前言
前几天我写的代码,都是把所有的内容写在main函数里,没有体现CPP面向对象的特性,我感觉很不好,所以接下来我的代码都会设计类,把不同的功能封装在类的成员函数里面。
我的思路
思路一 (哈希表记录链表的访问):
其实我最开始的思路就是设置一个visit数组
,大小为100,但是这里需要链表里面存储的data是不超过99的,这样我就能通过visit[Lnode->data]
在O(1)
的时间复杂度里面快速判断这个数组有没有被访问过。如果遍历到一个被访问过的结点,那就说明这个链表有环。
思路二 (双指针,快指针在前,慢指针在后):
这个思路最开始我没想到,参考了教程。其实原理就在于:
设想有两个人在操场上面跑步,一个人跑的比另外一个人快,那么最后快的肯定能追上慢的,这个时候快的已经比慢的领先一圈了。
我们考虑用双指针来实现,一个指针一步一步的走,一个指针两步两步的走。最后如果这两个指针能重合,那么就说明有环。
值得注意的是,这里的判断条件稍微有点复杂,null->next,cpp是会报错的
。
- 为什么要这样设置?
- 看这里 小浩算法–题解–环形链表
我的代码
#include<iostream>
#include <unordered_map>
using namespace std;typedef struct Lnode {int data;struct Lnode* next;Lnode(int val) :data(val), next(NULL) {}
};class LinkedList {
private:Lnode* head;Lnode* rear;int node_num;public:LinkedList() : head(nullptr),rear(head) {cout << "请输入链表的结点总数" << endl;cin >> this->node_num;int nodeData;//把链表的总长度存储在头结点的数据域head = new Lnode(node_num);Lnode* p = head;Lnode* q;for (int i = 0; i < node_num; i++) {cin >> nodeData;q = new Lnode(nodeData);p->next = q;p = p->next;}p = head->next;//输出生成的链表cout << "您已经生成如下链表: " << endl;while (p->next != NULL) {cout << p->data << " -> ";p = p->next;}cout << p->data<<endl;rear = p;}~LinkedList() {Lnode* current = head;while (current != rear->next && current != nullptr) {Lnode* next = current->next;delete current;current = next;}}void append(int val) {rear->next = new Lnode(val);rear = rear->next;}void generateRing(int x) {Lnode* ring_place = head;while (x-- != 0) {ring_place = ring_place->next;}rear->next = ring_place;}void print_ring_des() {cout << "环的终点是:" << rear->next->data << endl;}//根据哈希表来判断是否是个环void check_Ring() {Lnode* p = head;unordered_map<Lnode*, int> m;while (p != nullptr) {// 如果当前节点已存在于map中,则表示存在环if (m.find(p) != m.end()) {cout << "========哈希表结果:================" << endl;cout << "链表存在环!" << endl;return;}// 将当前节点加入mapm[p] = 1;p = p->next;}// 遍历结束,未发现环cout << "========哈希表结果:================" << endl;cout << "链表不存在环!" << endl;}/// <summary>/// 利用双指针跑圈来判断是否有环,一个跑慢点(每次遍历1一个),一个跑快点(每次遍历2个)/// </summary>void check_Ring_2() {Lnode* slow = head, *fast = head->next;while (fast->next != nullptr && slow != fast &&fast != nullptr) {slow = slow->next;fast = fast->next->next;}if (slow == fast) {cout << "=======双指针跑圈结果:=================" << endl;cout << "链表存在环!" << endl;}else {cout << "=======双指针跑圈结果:=================" << endl;cout << "链表不存在环!" << endl;}}
};int main() {LinkedList Llist;Llist.generateRing(2);Llist.print_ring_des();Llist.check_Ring();Llist.check_Ring_2();
}
运行结果