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;
}
相关推荐
一只侯子5 小时前
Tuning——CC调试(适用高通)
开发语言·图像处理·笔记·学习·算法
丁浩6665 小时前
Python机器学习---1.数据类型和算法:线性回归
开发语言·python·机器学习·线性回归
那年窗外下的雪.5 小时前
鸿蒙ArkUI布局与样式进阶(十二)——自定义TabBar + class类机制全解析(含手机商城底部导航案例)
开发语言·前端·javascript·华为·智能手机·harmonyos·arkui
Larry_Yanan5 小时前
QML学习笔记(四十六)QML与C++交互:Q_PROPERTY宏映射
c++·笔记·qt·学习·ui·交互
马拉萨的春天5 小时前
探索Objective-C中的对象复制:深入理解copy和mutableCopy
开发语言·ios·objective-c
再睡一夏就好5 小时前
【C++闯关笔记】深究继承
java·数据结构·c++·stl·学习笔记
啊森要自信5 小时前
【MySQL 数据库】使用C语言操作MySQL
linux·c语言·开发语言·数据库·mysql
千码君20165 小时前
Go语言:对其语法的一些见解
开发语言·后端·golang
mjhcsp6 小时前
C++ char 类型深度解析:字符与字节的双重身份
开发语言·c++·char