C++ 双向循环链表

c++中双向循环链表的第一部分是数据域,用于存储具体的数据信息,这个数据可以是任何类型,取决于具体的应用场景。第二部分是指向前驱节点的指针prev,第三部分是指向后继节点的指针next,同样和prev一样是一个引用或指针。

双向循环链表:头插法,先创建一个节点,将节点的prev指向虚拟头结点,将节点的next指向虚拟头结点的下一个节点,最后将对应节点的指针指向对应位置。

尾插法,先创建一个节点,将节点的prev指向虚拟头结点的prev所指向的指针,将节点的next指针指向虚拟头结点,最后将对应节点的指针指向对应位置。

任意插,找到需要插入的指针后,新节点的prev指向插入节点位置的节点,新节点next指向插入节点位置的下一个节点,最后将节点的指针分别指向对应位置。

节点删除,将节点的前一个节点的next指针指向后一个节点,将后一个节点的prev指向节点前一个节点。并且释放节点的内存。注意,删除的节点不能是虚拟头结点。

代码见下:

cpp 复制代码
#include<iostream>
using namespace std;

//双向循环链表
template<typename T>
struct Node {
	T data;
	Node* prev;
	Node* next;
	Node(const T& value) :data(value), prev(NULL), next(NULL) {

	}
};

template<class T>
class DoublyLinkedList {
public:
	DoublyLinkedList();
	~DoublyLinkedList();

	void push_front(const T& value);
	void push_back(const T& value);
	void insert_after(Node<T>* node, const T& value);
	void delete_node(Node<T>* node);
	void modify(Node<T>* node, const T& value);
	Node<T>* find(const T& value) const;

	void print() const;
	int size() const;
	bool empty() const;

private:
	Node<T>* m_dummyHead;
	int m_size;
};

template<class T>
DoublyLinkedList<T>::DoublyLinkedList(): m_size(0)
{
	m_dummyHead = new Node<T>(T());
	m_dummyHead->prev = m_dummyHead;
	m_dummyHead->next = m_dummyHead;
}

template<class T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
	while (m_size > 0) {
		delete_node(m_dummyHead->next);
	}
	delete m_dummyHead;
	m_dummyHead = NULL;
}

template<class T>
void DoublyLinkedList<T>::push_front(const T& value)
{
	Node<T>* newNode = new Node<T>(value);
	newNode->prev = m_dummyHead;
	newNode->next = m_dummyHead->next;

	m_dummyHead->next->prev = newNode;
	m_dummyHead->next = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::push_back(const T& value)
{
	Node<T>* newNode = new Node<T>(value);

	newNode->prev = m_dummyHead->prev;
	newNode->next = m_dummyHead;

	m_dummyHead->prev->next = newNode;
	m_dummyHead->prev = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::insert_after(Node<T>* node, const T& value)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	Node<T>* newNode = new Node<T>(value);

	newNode->prev = node;
	newNode->next = node->next;

	node->next->prev = newNode;
	node->next = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::delete_node(Node<T>* node)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	node->prev->next = node->next;
	node->next->prev = node->prev;
	delete node;
	--m_size;
}

template<class T>
void DoublyLinkedList<T>::modify(Node<T>* node, const T& value)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	node->data = value;
}

template<class T>
Node<T>* DoublyLinkedList<T>::find(const T& value) const
{
	Node<T>* curr = m_dummyHead->next;
	while (curr != m_dummyHead) {
		if (curr->data == value) {
			return curr;
		}
		curr = curr->next;
	}
	return NULL;
}

template<class T>
void DoublyLinkedList<T>::print() const
{
	Node<T>* curr = m_dummyHead->next;
	while (curr != m_dummyHead) {
		cout << curr->data << " ";
		curr = curr->next;
	}
	cout << endl;
}

template<class T>
int DoublyLinkedList<T>::size() const
{
	return m_size;
}

template<class T>
bool DoublyLinkedList<T>::empty() const
{
	return m_size == 0;
}









int main() {
	DoublyLinkedList<char> dll;
	dll.push_back('i'); dll.print();
	dll.push_back('c'); dll.print();
	dll.push_back('p'); dll.print();
	dll.push_back('c'); dll.print();

	dll.push_front('m'); dll.print();
	dll.push_front('a'); dll.print();

	Node<char>* nd = dll.find('a');
	dll.insert_after(nd, 'c'); dll.print();
	nd = dll.find('m');
	dll.insert_after(nd, '/'); dll.print();

	nd = dll.find('i');
	dll.modify(nd, 'c'); dll.print();

	nd = dll.find('m');
	dll.delete_node(nd); dll.print();

	cout << dll.empty() << endl;
	cout << dll.size() << endl;

	return 0;
}

代码练习1 对应蓝桥云课 小王子双链表 代码见下

cpp 复制代码
#include<iostream>
using namespace std;

//双向循环链表
template<typename T>
struct Node {
	T data;
	Node* prev;
	Node* next;
	Node(const T& value) :data(value), prev(NULL), next(NULL) {

	}
};

template<class T>
class DoublyLinkedList {
public:
	DoublyLinkedList();
	~DoublyLinkedList();

	void push_front(const T& value);
	void push_back(const T& value);
	void insert_after(Node<T>* node, const T& value);
	void delete_node(Node<T>* node);
	void modify(Node<T>* node, const T& value);
	Node<T>* find(const T& value) const;

	void print() const;
	int size() const;
	bool empty() const;

private:
	Node<T>* m_dummyHead;
	int m_size;
};

template<class T>
DoublyLinkedList<T>::DoublyLinkedList(): m_size(0)
{
	m_dummyHead = new Node<T>(T());
	m_dummyHead->prev = m_dummyHead;
	m_dummyHead->next = m_dummyHead;
}

template<class T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
	while (m_size > 0) {
		delete_node(m_dummyHead->next);
	}
	delete m_dummyHead;
	m_dummyHead = NULL;
}

template<class T>
void DoublyLinkedList<T>::push_front(const T& value)
{
	Node<T>* newNode = new Node<T>(value);
	newNode->prev = m_dummyHead;
	newNode->next = m_dummyHead->next;

	m_dummyHead->next->prev = newNode;
	m_dummyHead->next = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::push_back(const T& value)
{
	Node<T>* newNode = new Node<T>(value);

	newNode->prev = m_dummyHead->prev;
	newNode->next = m_dummyHead;

	m_dummyHead->prev->next = newNode;
	m_dummyHead->prev = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::insert_after(Node<T>* node, const T& value)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	Node<T>* newNode = new Node<T>(value);

	newNode->prev = node;
	newNode->next = node->next;

	node->next->prev = newNode;
	node->next = newNode;
	++m_size;
}

template<class T>
void DoublyLinkedList<T>::delete_node(Node<T>* node)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	node->prev->next = node->next;
	node->next->prev = node->prev;
	delete node;
	--m_size;
}

template<class T>
void DoublyLinkedList<T>::modify(Node<T>* node, const T& value)
{
	if (node == NULL || node == m_dummyHead) {
		return;
	}
	node->data = value;
}

template<class T>
Node<T>* DoublyLinkedList<T>::find(const T& value) const
{
	Node<T>* curr = m_dummyHead->next;
	while (curr != m_dummyHead) {
		if (curr->data == value) {
			return curr;
		}
		curr = curr->next;
	}
	return NULL;
}

template<class T>
void DoublyLinkedList<T>::print() const
{
	Node<T>* curr = m_dummyHead->next;
	while (curr != m_dummyHead) {
		cout << curr->data << " ";
		curr = curr->next;
	}
	cout << endl;
}

template<class T>
int DoublyLinkedList<T>::size() const
{
	return m_size;
}

template<class T>
bool DoublyLinkedList<T>::empty() const
{
	return m_size == 0;
}


int main() {
	DoublyLinkedList<int> dll;
	for (int i = 1; i <= 10; ++i) {
		dll.push_back(i);
	}
	int n;
	cin >> n;
	while (n--) {
		int x;
		cin >> x;
		Node<int>* nd = dll.find(x);
		dll.delete_node(nd);
		dll.push_front(x);
		dll.print();
	}

	return 0;
}
相关推荐
Aurorar0rua3 小时前
CS50 x 2024 Notes C -14
c语言·开发语言·学习方法
小短腿的代码世界4 小时前
从.qrc到rcc编译器:Qt资源系统的隐秘运作机制与大型项目性能突围
开发语言·qt
2401_833269304 小时前
Java网络编程入门
java·开发语言
青瓦梦滋4 小时前
C++的IO流与STL的空间配置器
开发语言·c++
五月君_5 小时前
Bun v1.3.14 发布,Rust 版即将进 Claude Code 内测,下一版可能就告别 Zig
开发语言·后端·rust
鱼很腾apoc6 小时前
【学习篇】第20期 超详解 C++ 多态:从语法规则到底层原理
java·c语言·开发语言·c++·学习·算法·青少年编程
不吃土豆的马铃薯7 小时前
4.SGI STL 二级空间配置器 allocate 与_S_refill 源码解析
c语言·开发语言·c++·dreamweaver·内存池
码界筑梦坊7 小时前
120-基于Python的食品营养特征数据可视化分析系统
开发语言·python·信息可视化·数据分析·毕业设计·echarts·fastapi
lsx2024067 小时前
《Foundation 模态框》
开发语言
fufu03117 小时前
vscode配置C/C++环境,用GDB调试简单程序分享
开发语言·c++