C++数据结构线性表的顺序存储之双链表(含有完整代码)

双链表

双链表是为了提高查表的效率,增加了前驱指针。
双链表特点:
1.寻找前驱节点时间复杂度减小
2.存放前驱指针额外空间
3.如果你引入last指针,在链表尾部插入指针会非常简单

实现代码

#include <iostream>
using namespace std;
//双链表中每个节点的定义
template <typename T>//T代表数据元素的的类型
struct DbNode
{
	T data;//数据域,存放数据元素
	DbNode<T>* prior;//前驱指针,指向前一个同类型的节点
	DbNode<T>* next;//后继指针,指向下一个同类型的节点
};
template <typename T>
class DbLinkList
{
public:
	DbLinkList();//构造函数
	~DbLinkList();//析构函数
	bool ListInsert(int i, const T& e);//在第I个位置插入
	bool ListDelete(int i);//在第I个位置删除
	bool DeleteNode(DbNode<T>* p);//删除节点
	bool GetElem(int i, T& e);//获取第I个位置的元素
	int LocateElem(const T& e);//按元素查找其在单链表第一次出现的的位置
	void DisplayList();//输出单链表中的所有元素
	int ListLength();//输出单链表的长度
	bool Empty();//判断单链表是否为空
	void ReverseDataList();//翻转单链表数据
	void ReverseList();//翻转单链表
	bool InsertPriorNode(DbNode<T>* pcurr, const T& e);
	bool ListDelete();
	//在链表某个节点之前插入节点
private:
	DbNode<T>* m_head;//头指针(指向链表第一个节点的指针)
	int m_length;//单链表当前长度
};
template <typename T>
DbLinkList<T>::DbLinkList()
{
	m_length = 0;//记录链表长度
	m_head = new DbNode<T>;//新建一个头结点
	m_head->next = nullptr;//头结点的后继节点赋值为空指针
	m_head->prior = nullptr;//头结点的前驱节点赋值为空指针
}
template <typename T>
DbLinkList<T>::~DbLinkList()
{
	
}
template <typename T>
bool DbLinkList<T>::ListInsert(int i, const T& e)
{
	if (i<1 || i>(m_length + 1))
	{
		cout << "插入位置不合法!插入失败!" << endl;
		return false;
	}
	if (m_length == 0)
	{
		DbNode<T>* pDbNode = new DbNode<T>;
		pDbNode->data = e;
		pDbNode->prior = m_head;
		pDbNode->next = nullptr;
		m_head->next = pDbNode;
		cout << "成功在位置" << i << "插入元素" << e << endl;
		m_length++;
		return true;
	}
	if (i == m_length + 1)
	{
		DbNode<T>* pDbNode = new DbNode<T>;//新建节点
		DbNode<T>* p_curr = m_head;
		for (int j = 0; j < i - 1; j++)
		{
			p_curr = p_curr->next;
		}//找到最后一个节点
		pDbNode->data = e;//传入数据域
		pDbNode->next = nullptr;//最后一个节点的后继赋值为空指针
		pDbNode->prior = p_curr;//最后一个节点的前驱指针赋值为之前的尾结点
		p_curr->next = pDbNode;//之前的尾结点的后继指针赋值为新的尾结点
		cout << "成功在位置" << i << "插入元素" << e << endl;
		m_length++;
		return true;
	}
	if (i >= 1 && i <= m_length)
	{
		DbNode<T>* pDbNode = new DbNode<T>;//新建节点
		DbNode<T>* p_curr = m_head;
		for (int j = 0; j < i-1; j++)
		{
			p_curr = p_curr->next;
		}//找到第i-1个节点
		pDbNode->data = e;//传入数据域
		pDbNode->next = p_curr->next;//连接后继节点
		p_curr->next = pDbNode;//更新后继节点
		(p_curr->next)->prior = pDbNode;//更新前驱结点
		pDbNode->prior = p_curr;//连接前驱节点
		cout << "成功在位置" << i << "插入元素" << e << endl;
		m_length++;
		return true;
	}
	else
	{
		return false;
	}
}
template <typename T>
bool DbLinkList<T>::InsertPriorNode(DbNode<T>* pcurr, const T& e)
{
	DbNode<T>* pDbNode = new DbNode<T>;//初始化新节点
	pDbNode->data = e;//给新节点的数据域赋值
	DbNode<T>* p_curr = pcurr->prior;//找到插入节点的前驱节点
	pDbNode->next = pcurr;//将新节点链上后继节点
	pDbNode->prior = p_curr;//将新节点链上前驱节点
	pcurr->prior = pDbNode;//更新插入节点的前驱节点
	p_curr->next = pDbNode;//更新插入节点前一个节点的后继节点
	return true;
}
template <typename T>
void DbLinkList<T>::DisplayList()
{
	DbNode<T>* p_curr = m_head->next;
	while (p_curr != nullptr)
	{
		cout << p_curr->data << " ";
		p_curr = p_curr->next;
	}
}
template <typename T>
bool DbLinkList<T>::ListDelete(int i)
{
	DbNode<T>* p_curr = m_head;
	if (i<1 || i>m_length)
	{
		cout << "删除位置不合法!" << endl;
		return false;
	}
	if (i == m_length)
	{
		for (int j = 0; j < i - 1; j++)
		{
			p_curr = p_curr->next;
		}
		DbNode<T>* p = p_curr->next;//找到第i位的节点
		cout << "已删除位置为" << i << "的节点," << "元素值为" << p->data << endl;
		delete p;//删除第i位的节点
		p_curr->next = nullptr;
		return true;
	}
	if (i >= 1 && i < m_length)
	{
		for (int j = 0; j < i - 1; j++)
		{
			p_curr = p_curr->next;
		}
		DbNode<T>* p = p_curr->next;//找到第i位的节点
		DbNode<T>* q = p->next;//找到第i+1位的节点
		cout << "已删除位置为" << i << "的节点," << "元素值为" << p->data << endl;
		delete p;//删除第i位的节点
		p_curr->next = q;//更新第i-1位节点的后继节点
		q->prior = p_curr;//更新第i+1位节点的前驱节点
		return true;
	}
	else
	{
		return false;
	}
}
template <typename T>
bool DbLinkList<T>::DeleteNode(DbNode<T>* p)
{
	DbNode<T>* p_curr;//获取p节点
	DbNode<T>* p_currP;//获取p节点的前驱节点
	DbNode<T>* p_currN;//获取p节点的后继节点
	p_currP = p->prior;//赋值
	p_curr = p;//赋值
	p_currN = p->next;//赋值
	p_currP->next = p_currN;//更新p节点的前驱节点的后继节点
	p_currN->prior = p_currP; //更新p节点的后继节点的前驱节点
	return true;
}
int main()
{
	DbLinkList<int> obj;
	obj.ListInsert(1, 12);
	obj.ListInsert(1, 24);
	obj.ListInsert(3, 48);
	obj.ListInsert(2, 100);
	obj.ListDelete(2);
	obj.DisplayList();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值