數據結構和算法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;
		}
	}
}

具體的實現效果如下圖所示:


一個雙向鏈表就實現完成了,該雙向鏈表具有實際意義,不僅僅是作爲演示使用的,可以使用在實際的項目之中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章