【小浩算法cpp题解】判断环形链表

发布于:2024-04-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

前言

前几天我写的代码,都是把所有的内容写在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;
			}
			// 将当前节点加入map
			m[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();
}

运行结果

在这里插入图片描述
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到