C++链表总结


1.单向链表

头节点不存储信息,尾节点存储信息,便于后续尾插
在这里插入图片描述

//单链表
class List
{
private:
	struct Node
	{
		int value;
		Node* next;
	};
	//头节点,不存储信息
	Node* head;
	//尾结点,便于后续尾插
	Node* tail;
	//数量
	int size;
public:
	List()
	{
		this->head = new Node;
		//开始时,head和tail重合
		this->tail = this->head;
		this->head->next = nullptr;
		this->size = 0;
	}
	//尾插
	void push_back(int data)
	{
		Node* pnew = new Node;
		pnew->value = data;
		pnew->next = nullptr;
		this->tail->next = pnew;
		this->tail = pnew;
		this->size++;
	}
	//尾删
	void pop_back()
	{
		//判断链表是否为空
		if (this->size == 0)
			return;
		//temp用于记录尾节点的前一个节点
		Node* temp = this->head;
		Node* del = this->head->next;
		while (del)
		{
			temp = del;
			del = del->next;
		}
		delete del;
		temp->next = nullptr;
		//删除del后,temp为尾结点,故tail指向temp
		this->tail = temp;
		this->size--;
	}
	//插入
	void Insert(int n, int data)
	{
		if (n<0 || n>this->size)
			return;
		else if (n == this->size)//插入到尾部
		{
			this->push_back(data);
			return;
		}
		else if (n == 0)//插入到头部
		{
			Node* pnew = new Node;
			pnew->value = data;
			pnew->next = this->head->next;
			this->head->next = pnew;
		}
		else//插入到其他位置
		{
			Node* temp = this->head->next;
			for (int i = 1; i < n; i++)
				temp = temp->next;
			Node* pnew = new Node;
			pnew->value = data;
			pnew->next = temp->next;
			temp->next = pnew;
		}
		this->size++;
	}
	//删除
	void Delete(int n)
	{
		if (n < 0 || n >= this->size)
			return;
		else if (n == this->size - 1)//尾删
		{
			this->pop_back();
			return;
		}
		else if (n == 0)//头删
		{
			Node* del = this->head->next;
			this->head->next = del->next;
			delete del;
		}
		else//删除其他节点
		{
			Node* temp = this->head->next;
			for (int i = 1; i < n; i++)
				temp = temp->next;
			Node* del = temp->next;
			temp->next = del->next;
			delete del;
		}
		this->size--;
	}
	//遍历链表
	void Travel()
	{
		Node* temp = this->head->next;
		while (temp)
		{
			cout << temp->value << " ";
			temp = temp->next;
		}
		cout << endl;
	}
	//链表反转
	void Reserve()
	{
		if (this->size <= 1)
			return;
		//当前节点要指向的新节点
		Node* pre = nullptr;
		//当前节点的下一个节点
		Node* temp = nullptr;
		//当前节点
		Node* cur = this->head->next;
		Node* flag = cur;
		while (cur)
		{
			temp = cur->next;
			cur->next = pre;
			pre = cur;
			cur = temp;
		}
		this->head->next = pre;
		this->tail = flag;
	}
	~List()
	{
		Node* temp = this->head->next;
		while (temp)
		{
			this->head->next = temp->next;
			delete temp;
			temp = this->head->next;
		}
		delete this->head;
	}
};

2.双向链表

在这里插入图片描述head和tail都不存储信息,只用于指向作用

//双向链表
class DList
{
private:
	struct DNode
	{
		int value;
		DNode* next;
		DNode* prev;
	};
	//头结点
	DNode* head;
	//尾节点
	DNode* tail;
	int size;
public:
	DList()
	{
		//头结点和尾节点都不存储信息,只用于指向作用
		this->head = new DNode;
		this->tail = new DNode;
		this->head->next = this->tail;
		this->tail->prev = this->head;
		this->head->prev = this->tail;
		this->tail->next = nullptr;
		this->size = 0;
	}
	//尾插
	void push_back(int data)
	{
		DNode* pnew = new DNode;
		pnew->value = data;
		//先将新节点的指向弄好
		pnew->next = this->tail;
		pnew->prev = this->tail->prev;
		//再更新旧节点的指向
		this->tail->prev->next = pnew;
		this->tail->prev = pnew;
		this->size++;
	}
	//尾删
	void pop_back()
	{
		if (this->size == 0)
			return;
		DNode* del = this->tail->prev;
		//更新节点指向
		del->prev->next = this->tail;
		this->tail->prev = del->prev;
		//删除节点
		delete del;
		this->size--;
	}
	//插入
	void Insert(int n, int data)
	{
		if (n<0 || n>this->size)
			return;
		else if (n == this->size)//尾插
		{
			this->push_back(data);
			return;
		}
		else if (n == 0)//头插
		{
			DNode* pnew = new DNode;
			pnew->value = data;
			pnew->prev = this->head;
			pnew->next = this->head->next;
			this->head->next->prev = pnew;
			this->head->next = pnew;
		}
		else//插入到其他位置
		{
			DNode* pnew = new DNode;
			pnew->value = data;
			//根据插入位置分成两种情况插入,以提高插入速度
			if (n <= this->size / 2)
			{
				DNode* temp = this->head->next;
				for (int i = 1; i < n; i++)
					temp = temp->next;
				pnew->next = temp->next;
				pnew->prev = temp;
				temp->next->prev = pnew;
				temp->next = pnew;
			}
			else
			{
				DNode* temp = this->tail->prev;
				for (int i = 1; i < this->size - n; i++)
					temp = temp->prev;
				pnew->prev = temp->prev;
				pnew->next = temp;
				temp->prev->next = pnew;
				temp->prev = pnew;
			}
		}
		this->size++;
	}
	//删除
	void Delete(int n)
	{
		if (n < 0 || n >= this->size)
			return;
		else if (n == this->size - 1)//尾删
		{
			this->pop_back();
			return;
		}
		else if (n == 0)//头删
		{
			DNode* del = this->head->next;
			del->next->prev = this->head;
			this->head->next = del->next;
			delete del;
		}
		else//删除其他节点
		{
			//根据删除位置分成两种情况删除,提高删除速度
			if (n <= this->size / 2)
			{
				DNode* temp = this->head->next;
				for (int i = 1; i < n; i++)
					temp = temp->next;
				DNode* del = temp->next;
				del->next->prev = temp;
				temp->next = del->next;
				delete del;
			}
			else
			{
				DNode* temp = this->tail->prev;
				for (int i = 1; i < this->size - n; i++)
					temp = temp->prev;
				DNode* del = temp->prev;
				del->prev->next = temp;
				temp->prev = del->prev;
				delete del;
			}
		}
		this->size--;
	}
	//遍历
	void Travel()
	{
		DNode* temp = this->head->next;
		while (temp != this->tail)
		{
			cout << temp->value << " ";
			temp = temp->next;
		}
		cout << endl;
	}
	~DList()
	{
		DNode* temp = this->head->next;
		while (temp != this->tail)
		{
			this->head->next = temp->next;
			delete temp;
			temp = this->head->next;
		}
		//删除头结点和尾节点
		delete this->head;
		delete this->tail;
	}
};

3.循环链表

head不
head不存储信息,只用于指向作用

//循环链表
//循环链表声明
template<typename T>
class CList;
//循环节点声明
template<typename T>
class CNode
{
	//将循环链表作为其友元类
	friend class CList<T>;
private:
	CNode* prev;
	CNode* next;
	//注意,如果T是自定义类型,还需要为T类型重载==运算符,以便后续的链表查找操作
	T value;
};
//循环链表定义
template<typename T>
class CList
{
private:
	//循环链表头指针,头指针不储存信息
	CNode<T>* head;
	int size;
public:
	CList()
	{
		this->head = new CNode<T>;
		this->head->next = this->head->prev = this->head;
		this->size = 0;
	}
	//尾插
	void push_back(const T& data)
	{
		CNode<T>* pnew = new CNode<T>;
		pnew->value = data;
		//先设置好新节点指向
		pnew->prev = this->head->prev;
		pnew->next = this->head;
		//更新其他节点指向
		this->head->prev->next = pnew;
		this->head->prev = pnew;
		this->size++;
	}
	//尾删
	void pop_back()
	{
		if (this->size == 0)
			return;
		CNode<T>* del = this->head->prev;
		//更新其他节点指向
		this->head->prev = del->prev;
		del->prev->next = this->head;
		//删除节点
		delete del;
		this->size--;
	}
	//插入
	void Insert(int n, const T& data)
	{
		if (n<0 || n>this->size)
			return;
		else if (n == this->size)//尾插
		{
			this->push_back(data);
			return;
		}
		else if (n == 0)//头插
		{
			CNode<T>* pnew = new CNode<T>;
			pnew->value = data;
			pnew->next = this->head->next;
			pnew->prev = this->head;
			this->head->next->prev = pnew;
			this->head->next = pnew;
		}
		else//插入到其他位置
		{
			CNode<T>* pnew = new CNode<T>;
			pnew->value = data;
			//根据插入位置分为不同插入情况
			if (n <= this->size / 2)
			{
				CNode<T>* temp = this->head->next;
				for (int i = 1; i < n; i++)
					temp = temp->next;
				pnew->next = temp->next;
				pnew->prev = temp;
				temp->next->prev = pnew;
				temp->next = pnew;
			}
			else
			{
				CNode<T>* temp = this->head->prev;
				for (int i = 1; i < this->size - n; i++)
					temp = temp->prev;
				pnew->prev = temp->prev;
				pnew->next = temp;
				temp->prev->next = pnew;
				temp->prev = pnew;
			}
		}
		this->size++;
	}
	//删除
	void Delete(int n)
	{
		if (n < 0 || n >= this->size)
			return;
		else if (n == this->size - 1)//尾删
		{
			this->pop_back();
			return;
		}
		else if (n == 0)//头删
		{
			CNode<T>* temp = this->head->next;
			temp->next->prev = this->head;
			this->head->next = temp->next;
			delete temp;
		}
		else//删除其他位置
		{
			//根据删除位置分为两种删除情况,提高删除效率
			if (n <= this->size / 2)
			{
				CNode<T>* temp = this->head->next;
				for (int i = 1; i < n; i++)
					temp = temp->next;
				CNode<T>* del = temp->next;
				temp->next = del->next;
				del->next->prev = temp;
				delete del;
			}
			else
			{
				CNode<T>* temp = this->head->prev;
				for (int i = 1; i < this->size - n; i++)
					temp = temp->prev;
				CNode<T>* del = temp->prev;
				temp->prev = del->prev;
				del->prev->next = temp;
				delete del;
			}
		}
		this->size--;
	}
	//遍历
	void Travel()
	{
		CNode<T>* temp = this->head->next;
		while (temp != this->head)
		{
			cout << temp->value << " ";
			temp = temp->next;
		}
		cout << endl;
	}
	~CList()
	{
		CNode<T>* temp = this->head->next;
		while (temp != this->head)
		{
			this->head->next = temp->next;
			delete temp;
			temp = this->head->next;
		}
		//删除头结点
		delete this->head;
	}
};

4.静态链表

//静态链表
class SList
{
private:
	//静态节点
	struct SNode
	{
		//值
		int value;
		//下一个节点的序号
		int next;
		//上一个节点的序号
		int pre;
	};
	//节点数组
	SNode arr[1000];
	//链表起始节点的序号
	int start;
	//当前链表的最后一个节点的序号
	int end;
	//链表的下一个节点序号
	int next;
	//记录节点个数
	int size;
public:
	SList()
	{
		//初始化节点数组
		for (int i = 0; i < 1000; i++)
		{
			arr[i].next = i + 1;
			arr[i].pre = i - 1;
		}
		//开始时,start,end,next都指向0
		this->start = 0;
		this->end = 0;
		this->next = 0;
		this->size = 0;
		//最后一个节点的下一个节点为-1,代表此时数组已满
		arr[999].next = -1;
	}
	//尾插
	void push_back(int data)
	{
		if (this->next == -1)
			return;
		arr[next].value = data;
		//更新end和next
		this->end = next;
		this->next = arr[next].next;
		this->size++;
	}
	//尾删
	void pop_back()
	{
		if (this->size == 0)
			return;

		//更新next和end
		this->next = this->end;
		this->end = arr[this->end].pre;
		this->size--;
	}
	//插入
	void Insert(int n,int data)
	{
		if (n<0 || n>this->size)
			return;
		else if (n == this->size)//尾插
		{
			this->push_back(data);
			return;
		}
		else if (n == 0)//头插
		{
			//记录当前的next值
			int temp = this->next;
			//更新end节点指向
			arr[this->end].next = arr[temp].next;
			arr[arr[temp].next].pre = this->end;
			//更新next值
			this->next = arr[temp].next;
			arr[temp].value = data;
			//更新start和temp指向
			arr[temp].next = this->start;
			arr[this->start].pre = temp;
			arr[temp].pre = -1;
			//更新start
			this->start = temp;
		}
		else//插入到其他位置
		{
			//记录当前next
			int temp = this->next;
			int ans = this->start;
			for (int i = 1; i < n; i++)
				ans = this->arr[ans].next;
			//更新end指向
			arr[this->end].next = arr[temp].next;
			arr[arr[temp].next].pre = this->end;
			//更新next
			this->next = arr[temp].next;
			//更新temp指向
			arr[temp].value = data;
			arr[temp].pre = ans;
			arr[temp].next = arr[ans].next;
			arr[arr[ans].next].pre = temp;
			arr[ans].next = temp;
		}
		this->size++;
	}
	//删除
	void Delete(int n)
	{
		if (n < 0 || n >= this->size)
			return;
		else if (n == this->size - 1)//尾删
		{
			this->pop_back();
			return;
		}
		else if (n == 0)//头删
		{
			//记录删除节点索引
			int del = this->start;
			//更新start
			this->start = arr[del].next;
			arr[this->start].pre = -1;
			//更新next
			this->next = del;
			//更新del指向
			arr[del].next = arr[this->end].next;
			arr[del].pre = this->end;
			arr[arr[this->end].next].pre = del;
			arr[this->end].next = del;
			//更新next
			this->next = del;
		}
		else//删除其他位置
		{
			int ans = this->start;
			for (int i = 1; i < n; i++)
				ans = arr[ans].next;
			//记录删除节点索引
			int del = arr[ans].next;
			//更新节点指向
			arr[ans].next = arr[del].next;
			arr[arr[del].next].pre = ans;
			//更新next
			this->next = del;
			//更新next指向
			arr[del].next = arr[this->end].next;
			arr[del].pre = this->end;
			arr[arr[this->end].next].pre = del;
			arr[this->end].next = del;
			//更新next
			this->next = del;
		}
		this->size--;
	}
	//遍历
	void Travel()
	{
		int n = this->start;
		for (int i = 0; i < this->size; i++)
		{
			cout << arr[n].value << " ";
			n = arr[n].next;
		}
		cout << endl;
	}
};

5.测试代码

//单链表的测试代码
void testList()
{
	List list;
	for (int i = 0; i < 5; i++)
		list.push_back(i * 10);
	list.Travel();
	list.Insert(0, 50);
	list.Insert(6, 60);
	list.Insert(3, 70);
	list.Travel();
	list.Reserve();
	list.Travel();
	list.pop_back();
	list.pop_back();
	list.Travel();
	list.Delete(0);
	list.Delete(4);
	list.Delete(2);
	list.Travel();
}
//双链表的测试代码
void testDList()
{
	DList list;
	for (int i = 0; i < 5; i++)
		list.push_back(i * 10);
	list.Travel();
	list.Insert(0, 50);
	list.Insert(6, 60);
	list.Insert(3, 70);
	list.Travel();
	list.pop_back();
	list.pop_back();
	list.Travel();
	list.Delete(0);
	list.Delete(3);
	list.Delete(2);
	list.Travel();
}
//循环链表的测试代码
void testCList()
{
	CList<int>list;
	for (int i = 0; i < 5; i++)
		list.push_back(i * 10);
	list.Travel();
	list.Insert(0, 50);
	list.Insert(6, 60);
	list.Insert(3, 70);
	list.Travel();
	list.pop_back();
	list.pop_back();
	list.Travel();
	list.Delete(0);
	list.Delete(3);
	list.Delete(2);
	list.Travel();
}
//静态链表的测试代码
void testSList()
{
	SList list;
	for (int i = 0; i < 5; i++)
		list.push_back(i * 10);
	list.Travel();
	list.Insert(0, 50);
	list.Insert(6, 60);
	list.Insert(3, 70);
	list.Travel();
	list.pop_back();
	list.pop_back();
	list.Travel();
	list.Delete(0);
	list.Delete(3);
	list.Delete(2);
	list.Travel();
}
int main()
{
	//testList();
	//testDList();
	//testCList();
	testSList();
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值