数据结构之双链表

来源:互联网 发布:淘宝子帐号超级管理员 编辑:程序博客网 时间:2024/05/27 01:45

数据结构双链表

双链表的各种操作也很简单,下边提供双链表 归并排序代码(经过本人测试)。归并排序采用迭代的自下向上方法,参考STL中list的sort方法。
#pragma once#ifndef _DLINLIST_HEADER_#define _DLINKLIST_HEADER_#include<algorithm>template<class T>struct DNode{T Val;DNode<T>* prev;DNode<T>* next;};template<class T>class DLinkList{public:DLinkList();DLinkList(const T* p, int nLen);void InsertHead(const T& Val);void InsertTail(const T& Val);void InsertByPos(const T& Val, int nIndex);void InsertByNode(DNode<T>* pNode, const int nPos);void DeteleHead();void DeleteTail();void DeteleByPos(int nIndex);//void DeletByVal(const T& Val);DNode<T>* FindByPos(int nIndex);int FindByVal(const T& Val);void PrintList();void PrintReserveList();bool empty();void Clear();int Length()const{return m_nLen;}//为归并排序准备的函数void Swap(DLinkList<T>& Ref);//交换两个链表void Splice(const int nDst, DLinkList<T>& Ref, const int nSrc);//摘链函数void Merge(DLinkList<T>& Ref);//将两个有序链表归并 并且将参数链表清空void reserve();void InsertSort();void MergeSort();//归并排序函数~DLinkList();private:DNode<T>* pHead;DNode<T>* pTail;int m_nLen;};template<class T>DLinkList<T>::DLinkList(){pHead = nullptr;pTail = nullptr;}template<class T>DLinkList<T>::DLinkList(const T* p, int nLen){if (nullptr == p || nLen < 1){throw ("参数非法!");}for (int i = 0; i < nLen; ++i){InsertTail(p[i]);}m_nLen = nLen;}template<class T>DLinkList<T>::~DLinkList(){Clear();}template<class T>void DLinkList<T>::InsertHead(const T& Val){DNode<T>* pNew = new DNode<T>;pNew -> Val = Val;if (nullptr == pHead){pHead = pNew;pHead->prev = nullptr;pHead->next = nullptr;pTail = pHead;++m_nLen;return;}pHead->prev = pNew;pNew->next = pHead;pHead = pNew;pHead->prev = nullptr;++m_nLen;}template<class T>void DLinkList<T>::InsertTail(const T& Val){if (nullptr == pTail){InsertHead(Val);return;}DNode<T>* pNew = new DNode<T>;pNew->Val = Val;pTail->next = pNew;pNew->prev = pTail;pTail = pNew;pTail->next = nullptr;++m_nLen;}template<class T>void DLinkList<T>::InsertByPos(const T& Val,const int nIndex){if (nIndex < 0 || nIndex > m_nLen){return;}if (0 == nIndex){InsertHead(Val);return;}if (nIndex == m_nLen){InsertTail(Val);return;}DNode<T>* pNew=new DNode<T>;pNew->Val = Val;DNode<T>* pPos;if (nIndex <= m_nLen / 2){pPos = pHead;for (int i = 0; i < nIndex; ++i){pPos = pPos->next;}pPos->prev->next = pNew;pNew->prev = pPos->prev;pPos->prev = pNew;pNew->next = pPos;}else{pPos = pTail;for (int i = 0; i < m_nLen - nIndex - 1; ++i){pPos = pPos->prev;}pPos->prev->next = pNew;pNew->prev = pPos->prev;pPos->prev = pNew;pNew->next = pPos;}++m_nLen;}template<class T>void DLinkList<T>::DeteleHead(){if (nullptr == pHead){return;}if (nullptr == pHead->next){delete pHead;pHead = nullptr;//切记不要忘记   pTailpTail = nullptr;--m_nLen;return;}DNode<T>* pTemp = pHead;pHead = pHead->next;pHead->prev = nullptr;delete pTemp;--m_nLen;}template<class T>void DLinkList<T>::DeleteTail(){if (nullptr == pTail || pHead->next==nullptr/*nullptr == pTail->prev*/){DeteleHead();return;}DNode<T>* pTemp = pTail;pTail = pTail->prev;pTail->next = nullptr;delete pTemp;--m_nLen;}template<class T>void DLinkList<T>::DeteleByPos(const int nIndex){if (nIndex < 0 || nIndex >= m_nLen){return;}if (0 == nIndex){DeteleHead();return;}if (m_nLen - 1 == nIndex){DeleteTail();return;}DNode<T>* pPos = FindByPos(nIndex);if (nullptr == pPos){return;}pPos->next - prev = pPos->prev;pPos->prev->next = pPos->next;delete pPos;pPos = nullptr;--m_nLen;}template<class T>int DLinkList<T>::FindByVal(const T& Val){DNode<T>* pTemp = pHead;int nPos = 0;while (pTemp != nullptr&&pTemp->Val != Val){pTemp = pTemp->next;++nPos;}if (nullptr == pTemp){return -1;}return nPos;}template<class T>DNode<T>* DLinkList<T>::FindByPos(const int nIndex){if (nIndex < 0 || nIndex >= m_nLen){return nullptr;}DNode<T>* pPos;if (nIndex <= m_nLen / 2){pPos = pHead;for (int i = 0; i < nIndex; ++i){pPos = pPos->next;}}else{pPos = pTail;for (int i = 0; i < m_nLen - nIndex - 1; ++i){pPos = pPos->prev;}}return pPos;}template<class T>void DLinkList<T>::PrintList(){if (nullptr == pHead){return;}DNode<T>* pTemp = pHead;while (pTemp != nullptr){cout << pTemp->Val;pTemp = pTemp->next;}cout << endl;}template<class T>void DLinkList<T>::PrintReserveList(){if (nullptr == pTail){return;}DNode<T>* pTemp = pTail;while (pTemp != nullptr){cout << pTemp->Val;pTemp = pTemp->prev;}cout << endl;}template<class T>void DLinkList<T>::Clear(){while (pHead != nullptr){DeleteTail();}m_nLen = 0;}//重要函数template<class T>void DLinkList<T>::reserve(){if (nullptr == pHead || nullptr == pHead->next){return;}DNode<T>* p1 = pHead;DNode<T>* p2 = p1->next;DNode<T>* p3 = p2->next;while (1){p2->next = p1;p2->prev = p3;if (nullptr == p3){break;}p1 = p2;p2 = p3;p3 = p3->next;}pHead->next = nullptr;pTail = pHead;//pTail->next == nullptr;//见鬼  。。。pHead = p2;pHead->prev = nullptr;}template<class T>void DLinkList<T>::InsertSort(){}//进阶函数template<class T>bool DLinkList<T>::empty(){return 0 == m_nLen;}template<class T>void DLinkList<T>::Swap(DLinkList<T>& Ref){DNode<T>* pTemp = pHead;pHead = Ref.pHead;Ref.pHead = pTemp;pTemp = pTail;pTail = Ref.pTail;Ref.pTail = pTemp;}template<class T>void DLinkList<T>::InsertByNode(DNode<T>* pNode, const int nPos){if (nullptr==pNode||nPos<0 || nPos>m_nLen){return;}//情况 很多 时 先罗列 特殊情况 if (nullptr == pHead){pHead = pTail=pNode;pHead->prev = nullptr;pTail->next = nullptr;++m_nLen;return;}if (0 == nPos){pNode->next = pHead;pHead->prev = pNode;pNode->prev = nullptr;pHead = pNode;++m_nLen;return;}else if (m_nLen == nPos){pTail->next = pNode;pNode->prev = pTail;pNode->next = nullptr;pTail = pNode;++m_nLen;return;}DNode<T>* pPos = FindByPos(nPos);if (nullptr == pPos){return;}//此时  不在开头  也不在结尾pPos->prev->next = pNode;pNode->prev = pPos->prev;pPos->prev = pNode;pNode->next = pPos;++m_nLen;}template<class T>void DLinkList<T>::Splice(const int nDst, DLinkList<T>& Ref, const int nSrc){if (nDst<0||nSrc<0||nullptr==Ref.pHead||nDst > m_nLen || nSrc >= Ref.m_nLen){return;}DNode<T>* pSrc = Ref.FindByPos(nSrc);if (nullptr == pSrc){return;}if (0 == nSrc){//处理原链表 和头删  相同  但是 不可以删除 因此 可以将头删 价参数 重写Ref.pHead = Ref.pHead->next;//一定要注意 摘链时 可能原链表被摘空的情况if (nullptr != Ref.pHead){Ref.pHead->prev = nullptr;}else{pTail = nullptr;}}else if (Ref.m_nLen-1 == nSrc){Ref.pTail = Ref.pTail->prev;if (nullptr != Ref.pTail){Ref.pTail->next = nullptr;}else{pHead = nullptr;}}else{pSrc->next->prev = pSrc->prev;pSrc->prev->next = pSrc->next;}--Ref.m_nLen;InsertByNode(pSrc, nDst);}template<class T>void DLinkList<T>::Merge(DLinkList<T>& Ref){//将 Ref 与 *this归并 至 *this  并且 Ref清空if (pHead == Ref.pHead){//防止自赋值return;}if (nullptr == Ref.pHead){return;}if (nullptr == pHead){Swap(Ref);/*pHead = Ref.pHead;pTail = Ref.pTail;//处理原链表 Ref.pHead = Ref.pTail = nullptr;m_nLen = Ref.m_nLen;Ref.m_nLen = 0;*/return;}DNode<T>* p1 = pHead;DNode<T>* p2 = Ref.pHead;if (p1->Val < p2->Val){pHead = p1;p1 = p1->next;}else{pHead = p2;p2 = p2->next;}pHead->prev = nullptr;DNode<T>* pCur;//保存带待插入节点DNode<T>* pPos = pHead;//保存插入位置前一个节点while (p1 != nullptr&&p2 != nullptr){if (p1->Val < p2->Val){pCur = p1;p1 = p1->next;}else{pCur = p2;p2 = p2->next;}pPos->next = pCur;pCur->prev = pPos;pPos = pPos->next;}if (nullptr == p1){pPos->next = p2;if (nullptr != p2){p2->prev = pPos;}//切记不要忘记处理链尾 pTail = Ref.pTail;}else{pPos->next = p1;if (nullptr != p1){p1->prev = pPos;}pTail = pTail;}//处理原链表//必须将原链表 赋空  否则 两个链表共享同一内存空间 //第一次析构 pHead不为空  析构成功  但是第二次析构 时pHead可能也也不为空 delete时造成错误//如果链表共享 同一个 pHead 则不会 处错误Ref.pHead = Ref.pTail = nullptr;m_nLen += Ref.m_nLen;Ref.m_nLen = 0;//PrintReserveList();}//深究函数template<class T>void DLinkList<T>::MergeSort(){if (nullptr == pHead || nullptr == pHead->next){return;}DLinkList<T> Counter[64];//看实际情况 如果节点较大 则new出来 但是堆栈空间操作快DLinkList<T> Carry;//只作为一个临时变量 搬运工角色int i = 0, fill = 0;while (!empty()){i = 0;Carry.Splice(0,*this,0);while (i < fill&&!(Counter[i].empty())){Counter[i].Merge(Carry);Carry.Swap(Counter[i]);++i;}Carry.Swap(Counter[i]);if (i == fill){++fill;}}for (i = 1; i < fill; ++i){Counter[i].Merge(Counter[i-1]);}Carry.pHead = Carry.pTail = nullptr;Swap(Counter[fill-1]);}#endif

0 0
原创粉丝点击