数据结构和算法C++语言实现:双向链表

1、双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。


2、如果对链表还不熟悉,可以看链表的基础知识 和 链表的实现  这两篇文章中对链表做了详细的介绍,并且进行了相关的实现。有了上述的基础知识,我们来实现双向链表就很简单了。

3、使用面向对象的方式来实现双向链表,首先需要对节点进行相关的构建

class Node
	{
	public:
		//后继
		Node *pNext;
		//前驱
		Node *pPrev;
		T m_data;

		Node()
		{
			memset(&m_data, 0, sizeof(m_data));
			pNext = NULL;
			pPrev = NULL;
		}

		~Node()
		{
			
		}

		Node(const Node &node)
		{
			this->m_data = node.m_data;
			this->pNext = node.pNext;
			this->pPrev = node.pPrev;
		}

		Node & operator=(const Node &node)
		{
			if (this == &node)
				return *this;

			this->m_data = node.m_data;
			this->pNext = node.pNext;
			this->pPrev = node.pPrev;
		}
	};

该节点中有一个后继,有一个前驱,用来从两个方向遍历链表中的元素,还有一个模板类型的数据结构。

有了上面的模型,我们就需要考虑该如何构建双向链表,以及该如何实现该双向链表了:

1)、链表能够在头部和尾部插入

2)、链表能够在任意的位置插入

3)、链表能够进行修改任意位置的值

4)、能够销毁整个链表

public:
	COpenList();
	COpenList(const COpenList &m_List);
	~COpenList();
	const COpenList& operator=(const COpenList &m_List);

	const T GetHead();
	const T GetTail();

	void AddHead(T data);
	void AddTail(T data);
	void RemoveAll();
	void RemoveHead();
	void RemoveTail();

	T GetAt(int nIndex);
	void RemoveAt(int nIndex);
	void SetAt(int nIndex, T num);

	void InsertAfter(int nIndex, T num);
	void InsertBefore(int nIndex, T num);

	int GetSize() const;
	bool IsEmpty();
    
	void PrintList();
	Node* GetHeadPtr();
	Node* GetTailPtr();
protected:

	//Link_List pHead;
	Node *pHead;
	Node *pTail;
	int m_Lenth;

双向链表的构建到此就完成了,接下来就是具体的实现了。

拷贝构造函数:

template<typename T>
COpenList<T>::COpenList(const COpenList<T> &m_List)
{
	if (!IsEmpty())
	{
		RemoveAll();
	}

	Node *pTempNode = m_List.pHead;
	if (NULL == pTempNode)
	{
		cout << "List doesn't exists" << endl;
		return;
	}

	this->pHead = new Node;
	this->pTail = new Node;
	this->m_Lenth =0;
	assert(pHead);

	Node *pNewHead = pHead;
	
	pNewHead->m_data = pTempNode->m_data;
	pTail->m_data = pTempNode->m_data;
	pTail->pNext = NULL;
	pTail->pPrev = pNewHead;
	pNewHead->pNext = pTail;
	pNewHead->pPrev = NULL;

	++m_Lenth;

	while(NULL!=pTempNode->pNext)
	{

		if (m_Lenth == m_List.GetSize() - 1)
		{
			pTail->m_data = pTempNode->pNext->m_data;
			pTail->pNext = NULL;
			pTail->pPrev = pNewHead;
			pNewHead->pNext = pTail;
		}
		else
		{
			Node *pTemp = new Node;
			if (NULL != pTemp)
			{
				pTemp->m_data = pTempNode->pNext->m_data;
				pTemp->pNext = NULL;
			}

			pNewHead->pNext = pTemp;
			pTemp->pPrev = pNewHead;
			pNewHead = pNewHead->pNext;
		}
		
		pTempNode = pTempNode->pNext;
		++m_Lenth;
	}

}

相关操作:

template<typename T>
const T COpenList<T>::GetHead()
{
	T result = 0;
	if (!IsEmpty())
		result = pHead->m_data;
	else
	{
		cerr << "EmptyList" << endl;
	}
		
	return result;
}

template<typename T>
const T COpenList<T>::GetTail()
{
	T result = 0;
	if (!IsEmpty())
		result = pTail->m_data;
	else
	{
		cerr << "EmptyList" << endl;
	}
	
	return result;
}

template<typename T>
bool COpenList<T>:: IsEmpty()
{
	return m_Lenth==0;
}

template<typename T>
int COpenList<T>::GetSize() const
{
	return m_Lenth;
}

template<typename T>
void COpenList<T>::AddHead(T data)
{
	if (IsEmpty())
	{
		pHead = new Node;
		pHead->m_data = data;
		pTail = new Node;
		pTail->m_data = data;

		pHead->pNext = pTail;
		pHead->pPrev = NULL;
		pTail->pPrev = pHead;
		pTail->pNext = NULL;
	}
	else if (1 == GetSize())
	{
		pHead->m_data = data;
		pHead->pNext = pTail;
	}
	else
	{
		Node *pNode = new Node;
		pNode->m_data = data;
		pNode->pNext = pHead;
		pHead->pPrev = pNode;


		pHead = pNode;
	}
	

	++m_Lenth;
}

template<typename T>
void COpenList<T>::AddTail(T data)
{
	if (IsEmpty())
	{
		pHead = new Node;
		pHead->m_data = data;
		pTail = new Node;
		pTail->m_data = data;

		pHead->pNext = pTail;
		pHead->pPrev = NULL;
		pTail->pNext = NULL;
		pTail->pPrev = pHead;
	}
	else if (1 == GetSize())
	{
		pTail->m_data = data;
	}
	else
	{
		Node *pNode = new Node;
		pNode->m_data = data;
		pNode->pNext = NULL;

		pTail->pNext = pNode;
		pNode->pPrev = pTail;

		pTail = pNode;
	}
	

	++m_Lenth;
}

template<typename T>
void COpenList<T>::RemoveAll()
{
	if (IsEmpty())
		return;


	Node *pTemp = pHead;
	Node *pTempIter = pTemp;
	while (NULL != pTemp)
	{
		pTempIter = pTemp->pNext;
		delete pTemp;
		pTemp = pTempIter;
	}

	m_Lenth = 0;
}

template<typename T>
void COpenList<T>::RemoveHead()
{
	if (IsEmpty())
		return;
	else if (1 == GetSize())
		RemoveAll();
	else
	{
		Node *pTemp = pHead;
		pHead = pHead->pNext;

		delete pTemp;

		pHead->pPrev = NULL;
	}

	--m_Lenth;
}

template<typename T>
void COpenList<T>::RemoveTail()
{
	if (IsEmpty())
		return;
	else if(1 == GetSize())
	{
		RemoveAll();
	}
	else
	{
		Node *pTemp = pTail->pPrev;
		delete pTail;

		pTail = pTemp;
		pTail->pNext = NULL;
	}

	--m_Lenth;
}

template<typename T>
T COpenList<T>::GetAt(int nIndex)
{
	T result = 0;
	if (nIndex >= GetSize())
		cerr << "Wrong Index" << endl;
	else
	{
		int nCount = 0;
		Node *pTemp = pHead;
		while (pTemp)
		{
			if (nCount == nIndex)
			{
				result =  pTemp->m_data;
			}

			pTemp = pTemp->pNext;
			++nCount;
		}
	}

	return result;
}

template<typename T>
void COpenList<T>::RemoveAt(int nIndex)
{
	if (nIndex >= GetSize())
	{
		cerr << "Wrong Index" << endl;
		return;
	}
	else
	{
		if (nIndex == 0)
		{
			RemoveHead();
		}
		else if (nIndex == GetSize()-1)
		{
			RemoveTail();
		}
		else
		{
			int nCount = 0;
			Node *pTemp = pHead;
			while (pTemp)
			{
				if (nCount == nIndex)
				{
					Node *pTempPrev = pTemp->pPrev;
					Node *pTempNext = pTemp->pNext;

					if (NULL != pTempPrev)
						pTempPrev->pNext = pTempNext;
					if (NULL != pTempNext)
						pTempNext->pPrev = pTempPrev;

					delete pTemp;

					break;
				}

				pTemp = pTemp->pNext;
				++nCount;
			}
		}

		--m_Lenth;
		
	}
}

template<typename T>
void COpenList<T>::SetAt(int nIndex, T num)
{
	if (nIndex >= GetSize())
		return;
	else
	{
		int nCount = 0;
		Node *pTemp = pHead;
		while (pTemp)
		{
			if (nCount == nIndex)
			{
				pTemp->m_data = num;
			}
			pTemp = pTemp->pNext;
			++nCount;
		}
	}
}

template<typename T>
void COpenList<T>::InsertAfter(int nIndex, T num)
{
	if (nIndex >= GetSize())
		return;
	else
	{
		int nCount = 0;
		Node *pTemp = pHead;
		while (pTemp)
		{
			if (nCount == nIndex)
			{
				Node *pNewNode = new Node;
				pNewNode->m_data = num;
				pNewNode->pNext = pTemp->pNext;
				pTemp->pNext = pNewNode;
				pNewNode->pPrev = pTemp;


				++m_Lenth;
				break;
			}

			++nCount;
			pTemp = pTemp->pNext;
		}
	}
}

template<typename T>
void COpenList<T>::InsertBefore(int nIndex, T num)
{
	if (nIndex >= GetSize())
		return;
	else
	{
		int nCount = 0;
		Node *pTemp = pHead;
		while (pTemp)
		{
			if (nCount == nIndex)
			{
				Node *pNewNode = new Node;
				pNewNode->m_data = num;
				pNewNode->pPrev = pTemp->pPrev;
				pTemp->pPrev = pNewNode;
				pNewNode->pNext = pTemp;

				++m_Lenth;
				break;
			}

			++nCount;
			pTemp = pTemp->pNext;
		}
	}
}

具体的实现效果如下图所示:


一个双向链表就实现完成了,该双向链表具有实际意义,不仅仅是作为演示使用的,可以使用在实际的项目之中。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值