【链表】还不会用C++实现链表?一文教会你各种链表的实现

2024-02-29 1634阅读

温馨提示:这篇文章已超过411天没有更新,请注意相关的内容是否还可用!

本文将用C++语言来实现数据结构中的无头单链表,带头循环链表,以及带头循环双向链表等链表结构(带头单链表与后两种链表的结构相似,实现起来比后两种更简单,读者阅读完本文即可自行实现)

【链表】还不会用C++实现链表?一文教会你各种链表的实现

一、无头单链表的实现

无头单链表在头插时需要改变头指针的位置,具体代码实现如下:

//无头单链表
#include 
#include 
using namespace std;
template 
//先定义链表中的节点
struct SListNode
{
	T data;
	SListNode* next;
	SListNode(T x)
	{
		this->data = x;
		this->next = nullptr;
	}
};
template 
class SList
{
private:
	//链表初始化后链表中就有一个节点
	SListNode* head;
	
public:
	SList(T x)
	{
		this->head = new SListNode(x);
	}
	~SList()
	{
		SListNode* cur = head;
		while (cur)
		{
			SListNode* next = cur->next;
			delete cur;
			cur = next;
		}
	}
	// 动态申请一个节点
	SListNode* BuySListNode(T x);
	// 单链表打印
	void SListPrint();
	// 单链表尾插
	void SListPushBack(T x);
	// 单链表的头插
	void SListPushFront(T x);
	// 单链表的尾删
	void SListPopBack();
	// 单链表头删
	void SListPopFront();
	// 单链表查找
	SListNode* SListFind(T x);
	// 单链表在pos位置之后插入x
	void SListInsertAfter(SListNode* pos, T x);
	// 单链表删除pos位置之后的值
	void SListEraseAfter(SListNode* pos);
};
template 
SListNode* SList:: BuySListNode(T x)
{
	SListNode* tmp = new SListNode(x);
	tmp->next = nullptr;
	return tmp;
}
template 
void SList::SListPrint()
{
	SListNode* cur =head;
	while (cur)
	{
		cout data next;
	}
	cout next;
	}
	SListNode* newnode = BuySListNode(x);
	cur->next = newnode;//连接
}
template 
void SList::SListPushFront(T x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = head;
	head = newnode;
}
template 
void SList::SListPopBack()
{
	assert(head);//头结点为空就不能继续删除了
	SListNode* tail = head;
	//链表中只有一个节点就只能删除头结点
	if (tail->next == nullptr)
	{
		delete head;
	}
	else
	{
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		delete tail->next;
		tail->next = nullptr;
	}
}
template 
void SList::SListPopFront()
{
	assert(head);
	SListNode* cur = head->next;
	delete head;
	head = cur;
}
template 
SListNode* SList::SListFind(T x)
{
	assert(head);
	SListNode* cur = head;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return nullptr;
}
template 
void SList::SListInsertAfter(SListNode* pos, T x)
{
	assert(pos);
	SListNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
template 
void SList::SListEraseAfter(SListNode* pos)
{
	assert(pos->next && pos);
	SListNode* cur = pos->next;
	pos->next = pos->next->next;
	delete cur;
}
int main()
{
	SList cur(1);
	cur.SListPushBack(2);
	cur.SListPushBack(3);
	cur.SListPushBack(4);
	cur.SListPushBack(5);
	cur.SListPushBack(6);
	cur.SListPrint();
	cur.SListPopFront();
	cur.SListPrint();
	cur.SListPopBack();
	cur.SListPrint();
	SListNode* p1 = cur.SListFind(2);
	cur.SListInsertAfter(p1, 20);
	cur.SListPrint();
	cur.SListEraseAfter(p1);
	cur.SListPrint();
	
	return 0;
}

二、带头循环链表的实现

带头意味着链表中会一直存在着一个头结点,无论链表的插入还是删除都是对头结点后面的节点进行的操作。头插的节点也是直接连接在头结点的下一个结点,不会改变头结点。循环意味着尾节点的next指针指向头节点,就像是形成了一个环一样。

具体实现代码如下:

#include 
#include 
using namespace std;
template 
struct Node
{
	T data;
	struct Node* next;
	Node()
	{
		this->data = 0;
		this->next = nullptr;
	}
	Node(T data)
	{
		this->data = data;
		this->next = nullptr;
	}
};
template 
class SList
{
private:
	Node* head;
	Node* tail;
public:
	SList()
	{
		this->head = new Node();
		this->tail = head;
	}
	~SList()
	{
		Node* p = head;
		Node* q = head;
		while (p != tail)
		{
			q = p->next;
			delete p;
			p = q;
		}
		delete tail;
	}
	
	// 动态申请一个节点
	Node* BuySListNode(T x);
	// 单链表打印
	void SListPrint();
	// 单链表尾插
	void SListPushBack(T x);
	// 单链表的头插
	void SListPushFront(T x);
	// 单链表的尾删
	void SListPopBack();
	// 单链表头删
	void SListPopFront();
	// 单链表查找
	Node* SListFind( T x);
	// 单链表在pos位置之后插入x
	void SListInsertAfter(Node* pos, T x);
	// 单链表删除pos位置之后的值
	void SListEraseAfter(Node* pos);
};
template 
Node* SList::BuySListNode(T x)
{
	Node* tmp = new Node;
	tmp->data = x;
	tmp->next = nullptr;
	return tmp;
}
template 
void SList::SListPrint()
{
	assert(head->next);//保证头节点后还有结点才打印,不然报错
	Node* cur = head->next;
	while (cur != head)
	{
		cout data next;
	}
	cout next = head;//尾节点的next指向头节点
}
template 
void SList::SListPushFront(T x)
{
	Node* newnode = BuySListNode(x);
	if (head == tail)
	{
		head->next = newnode;
		tail = newnode;
		tail->next = head;
	}
	else
	{
		newnode->next = head->next;
		head->next = newnode;
	}
}
template 
void SList::SListPopBack()
{
	assert(head->next);
	Node* cur = head;
	while (cur->next != tail)
	{
		cur = cur->next;
	}
	delete tail;
	tail = cur;
	tail->next = head;
}
template 
void SList::SListPopFront()
{
	assert(head->next);
	Node* cur = head->next;
	if (head->next == tail)
	{
		delete tail;
		tail = head;
	}
	else
	{
		head->next = cur->next;
		delete cur;
	}
}
template 
Node* SList::SListFind(T x)
{
	assert(head->next);
	Node* cur = head->next;
	while (cur != head)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return nullptr;
}
template 
void SList::SListInsertAfter(Node* pos, T x)
{
	assert(pos);
	if (pos->next == head)
	{
		SListPushBack(x);
	}
	else if(pos == head)
	{
		SListPushFront(x);
	}
	else
	{
		Node* newnode = BuySListNode(x);
		newnode->next = pos->next;
		pos->next = newnode;
	}
}
template 
void SList::SListEraseAfter(Node* pos)
{
	assert(pos);
	//尾节点后的头节点不能删
	if (pos->next == head)
	{
		exit(-1);
	}
	else if (pos == head)
	{
		SListPopFront();
	}
	else
	{
		Node* cur = pos->next;
		pos->next = pos->next->next;
		delete cur;
	}
}
int main()
{
	SList SL1;
	SL1.SListPushBack(1);
	SL1.SListPushBack(2);
	SL1.SListPushBack(3);
	SL1.SListPushBack(4);
	SL1.SListPushBack(5);
	SL1.SListPrint();
	SL1.SListPushFront(10);
	SL1.SListPrint();
	SL1.SListPopFront();
	SL1.SListPrint();
	SL1.SListPopBack();
	SL1.SListPrint();
	Node* cur = SL1.SListFind(2);
	SL1.SListInsertAfter(cur, 20);
	SL1.SListPrint();
	SL1.SListEraseAfter(cur);
	SL1.SListPrint();
	return 0;
}

三、带头双向循环链表的实现

具体实现思路与带头循环链表大同小异,只是在节点中需要增加一个指向前一个节点的指针。

具体实现代码如下:

#include 
#include 
using namespace std;
template 
struct Node
{
	T data;
	struct Node* prev;//指向前一个节点的指针
	struct Node* next;
	Node()
	{
		this->data = 0;
		this->prev = nullptr;
		this->next = nullptr;
	}
	Node(T data)
	{
		this->data = data;
		this->prev = nullptr;
		this->next = nullptr;
	}
};
template 
class SList
{
private:
	Node* head;//头节点
	Node* tail;//尾节点
public:
	SList()
	{
		this->head = new Node();
		head->next = nullptr;
		head->prev = nullptr;
		this->tail = head;
	}
	~SList()
	{
		Node* p = head;
		Node* q = head;
		while (p != tail)
		{
			q = p->next;
			delete p;
			p = q;
		}
		delete tail;
	}
	Node* getHead()
	{
		return this->head;
	}
	// 动态申请一个节点
	Node* BuySListNode(T x);
	// 单链表打印
	void SListPrint();
	// 单链表尾插
	void SListPushBack(T x);
	// 单链表的头插
	void SListPushFront(T x);
	// 单链表的尾删
	void SListPopBack();
	// 单链表头删
	void SListPopFront();
	// 单链表查找
	Node* SListFind(T x);
	// 单链表在pos位置之后插入x
	void SListInsertAfter(Node* pos, T x);
	// 单链表删除pos位置之后的值
	void SListEraseAfter(Node* pos);
};
template 
Node* SList::BuySListNode(T x)
{
	Node* tmp = new Node;
	tmp->data = x;
	tmp->prev = nullptr;
	tmp->next = nullptr;
	return tmp;
}
template 
void SList::SListPrint()
{
	assert(head->next);
	Node* cur = head->next;
	while (cur != head)
	{
		cout data next;
	}
	cout next = newnode;
	newnode->prev = tail;
	tail = newnode;
	tail->next = head;
	head->prev = tail;
}
template 
void SList::SListPushFront(T x)
{
	Node* newnode = BuySListNode(x);
	if (head == tail)//头节点后没有节点
	{
		head->next = newnode;
		newnode->prev = head;
		tail = newnode;
		tail->next = head;
		head->prev = tail;
	}
	else
	{
		newnode->next = head->next;
		newnode->prev = head;
		head->next = newnode;
	}
}
template 
void SList::SListPopBack()
{
	assert(head->next);
	Node* cur = tail->prev;
	head->prev = tail->prev;
	delete tail;
	tail = cur;
	tail->next = head;
	
}
template 
void SList::SListPopFront()
{
	assert(head->next);//只剩头节点不删
	Node* cur = head->next;
	if (head->next == tail)//头节点后只有一个节点
	{
		delete tail;
		tail = head;
		head->next = head;
		head->prev = head;
	}
	else
	{
		head->next = cur->next;
		cur->next->prev = head;
		delete cur;
	}
}
template 
Node* SList::SListFind(T x)
{
	assert(head->next);
	Node* cur = head->next;
	while (cur != head)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return nullptr;
}
template 
void SList::SListInsertAfter(Node* pos, T x)
{
	assert(pos);
	if (pos->next == head)
	{
		SListPushBack(x);
	}
	else if (pos == head)
	{
		SListPushFront(x);
	}
	else
	{
		Node* newnode = BuySListNode(x);
		newnode->next = pos->next;
		newnode->prev = pos;
		pos->next = newnode;
	}
}
template 
void SList::SListEraseAfter(Node* pos)
{
	assert(pos);
	if (pos->next == head)//尾节点后的头节点不删
	{
		exit(-1);
	}
	else if (pos == head)
	{
		SListPopFront();
	}
	else
	{
		Node* cur = pos->next;
		pos->next = pos->next->next;
		pos->next->prev = pos;
		delete cur;
	}
}
int main()
{
	//SListNode* head = new SListNode;
	SList SL1;
	SL1.SListPushBack(1);
	SL1.SListPushBack(2);
	SL1.SListPushBack(3);
	SL1.SListPushBack(4);
	SL1.SListPushBack(5);
	SL1.SListPrint();
	SL1.SListPushFront(10);
	SL1.SListPrint();
	SL1.SListPopFront();
	SL1.SListPrint();
	SL1.SListPopBack();
	SL1.SListPrint();
	Node* cur = SL1.SListFind(2);
	SL1.SListInsertAfter(cur, 20);
	SL1.SListPrint();
	SL1.SListEraseAfter(cur);
	SL1.SListPrint();
	return 0;
}
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]