双向链表的一个C++实现
来源:互联网 发布:农村淘宝的官网 编辑:程序博客网 时间:2024/06/06 00:40
下面是双向链表的一个C++实现,参考了《数据结构与算法分析C语言版》及不少牛人的分析总结,在此一并感谢了。在VC2005上经反复验证试验,结果非常不错,操作集合以后会继续增加。但可能还有不少bug,如果发现bug, 请告诉我一下。
注意:单链表及双向及循环链表均不使用表头(即哑节点,dummy node), 即m_pNodeHead指向链表的第一个真正的节点。
/*dlist.h*/#include <assert.h>#include <crtdbg.h>template<typename T>class Node{public:T data;Node<T> *prior;Node<T> *next;Node() : data(T()), prior(NULL), next(NULL) {}Node(const T &initdata) : data(initdata), prior(NULL), next(NULL) {}};template<typename T>class DList{protected:int m_nCount;Node<T> *m_pNodeHead;Node<T> *m_pNodeTail;public:DList();DList(const T &initdata);DList(const DList<T>& other);DList<T>& operator=(const DList<T>& other);~DList();public:////插入或删除需要注意处理:插入节点本身的next 和prior,前一个节点的next,后一个节点的prior.//注意在第一个节点或最后一个节点插入或删除时的特殊情况:前一个或后一个节点为NULL,而且注意移动m_pNodeHead或m_pNodeTailvoid Invert();int IsEmpty() const;int GetCount() const;int InsertBefore(const int pos, const T data);int InsertAfter(const int pos, const T data);int AddHead(const T data);int AddTail(const T data);void RemoveAt(const int pos);void RemoveHead();void RemoveTail();void RemoveAll();T& GetTail();T GetTail() const;T& GetHead();T GetHead() const;T& GetAt(const int pos);T GetAt(const int pos) const;void SetAt(const int pos, T data);int Find(const T data) const;int FindCircle() const;int FindCross(DList& testlist);T& GetPrev(int &pos);T& GetNext(int &pos);};template<typename T>inline DList<T>::DList() : m_nCount(0), m_pNodeHead(NULL), m_pNodeTail(NULL){}template<typename T>inline DList<T>::DList(const T &initdata): m_nCount(0), m_pNodeHead(NULL), m_pNodeTail(NULL){AddHead(initdata);}template<typename T>inline DList<T>::DList(const DList<T>& other): m_nCount(0), m_pNodeHead(NULL), m_pNodeTail(NULL){if(other.m_nCount>0){for(int i=1;i<=other.m_nCount;i++){AddTail(other.GetAt(i));}}}template<typename T>inline DList<T>& DList<T>::operator=(const DList<T>& other){if(this==&other){return *this;}if(m_nCount>0){RemoveAll();}if(other.m_nCount>0){for(int i=1;i<=other.m_nCount;i++){AddTail(other.GetAt(i));}}return *this;}template<typename T>inline DList<T>::~DList(){RemoveAll();}template<typename T>inline void DList<T>::Invert(){if(m_nCount<=1) return;Node<T> *tmpNod,*curNod,*nextNod;curNod=m_pNodeHead;for(int i=1;i<=m_nCount;i++){ nextNod=curNod->next;tmpNod=curNod->prior;curNod->prior=curNod->next;curNod->next=tmpNod;curNod=nextNod;}tmpNod=m_pNodeHead;m_pNodeHead=m_pNodeTail;m_pNodeTail=tmpNod;return;}//insert data before pos.template<typename T>inline int DList<T>::InsertBefore(const int pos, const T data){int i;int nRetPos;Node<T> *pTmpNode;Node<T> *pNewNode;try{pNewNode = new Node<T>;}catch(std::bad_alloc&){nRetPos = 0;return nRetPos;}pNewNode->data = data;// if the list is empty, replace the head node with the new node.if (NULL == m_pNodeHead){pNewNode->prior = NULL;pNewNode->next = NULL;m_pNodeHead = pNewNode;m_pNodeTail = pNewNode;nRetPos = 1;++m_nCount;return nRetPos;}// is pos range valid?ASSERT(1 <= pos && pos <= m_nCount);// insert before head node?if (1 == pos){pNewNode->prior = NULL;pNewNode->next = m_pNodeHead;m_pNodeHead->prior = pNewNode;m_pNodeHead = pNewNode;nRetPos = 1;++m_nCount;return nRetPos;}// if the list is not empty and is not inserted before head node,// seek to the pos of the list and insert the new node before it.pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}pNewNode->next = pTmpNode;pNewNode->prior = pTmpNode->prior;pTmpNode->prior->next = pNewNode;pTmpNode->prior = pNewNode;// if tail node, must update m_pNodeTailif (NULL == pNewNode->next){m_pNodeTail = pNewNode;}nRetPos = pos;++m_nCount;return nRetPos;}//insert data after postemplate<typename T>inline int DList<T>::InsertAfter(const int pos, const T data){int i;int nRetPos;Node<T> *pNewNode;Node<T> *pTmpNode;try{pNewNode = new Node<T>;}catch(std::bad_alloc&){nRetPos = 0;return nRetPos;}pNewNode->data = data;// if the list is empty, replace the head node with the new node.if (NULL == m_pNodeHead){pNewNode->prior = NULL;pNewNode->next = NULL;m_pNodeHead = pNewNode;m_pNodeTail = pNewNode;nRetPos = 1;++m_nCount;return nRetPos;}// is pos range valid?ASSERT(1 <= pos && pos <= m_nCount);// if the list is not empty,// seek to the pos of the list and insert the new node after it.pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}pNewNode->next = pTmpNode->next;pNewNode->prior = pTmpNode;pTmpNode->next = pNewNode; //modified by myself // if tail node, must update m_pNodeTailif(NULL==pNewNode->next){m_pNodeTail = pNewNode;}else{pNewNode->next->prior=pNewNode;}nRetPos = pos + 1;++m_nCount;return nRetPos;}template<typename T>inline T& DList<T>::GetAt(const int pos){ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}return pTmpNode->data;}template<typename T>inline T DList<T>::GetAt(const int pos) const{ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}return pTmpNode->data;}template<typename T>inline int DList<T>::AddHead(const T data){return InsertBefore(1, data);}template<typename T>inline int DList<T>::AddTail(const T data){return InsertAfter(GetCount(), data);}template<typename T>inline int DList<T>::IsEmpty() const{return 0 == m_nCount;}template<typename T>inline int DList<T>::GetCount() const{return m_nCount;}template<typename T>inline T& DList<T>::GetTail(){ASSERT(0 != m_nCount);return m_pNodeTail->data;}template<typename T>inline T DList<T>::GetTail() const{ASSERT(0 != m_nCount);return m_pNodeTail->data;}template<typename T>inline T& DList<T>::GetHead(){ASSERT(0 != m_nCount);return m_pNodeHead->data;}template<typename T>inline T DList<T>::GetHead() const{ASSERT(0 != m_nCount);return m_pNodeHead->data;}//as its name, delete the data at postemplate<typename T>inline void DList<T>::RemoveAt(const int pos){ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;// head node?if (1 == pos){m_pNodeHead = m_pNodeHead->next;if(m_pNodeHead){m_pNodeHead->prior=NULL;} delete pTmpNode;--m_nCount;if (0 == m_nCount){m_pNodeTail = NULL;}return;}//otherwise...for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}pTmpNode->prior->next = pTmpNode->next;//last node?if(pTmpNode->next){pTmpNode->next->prior=pTmpNode->prior;}else{m_pNodeTail=pTmpNode->prior;}delete pTmpNode;--m_nCount;if (0 == m_nCount){m_pNodeTail = NULL;}return;}template<typename T>inline void DList<T>::RemoveHead(){ASSERT(0 != m_nCount);RemoveAt(1);}template<typename T>inline void DList<T>::RemoveTail(){ASSERT(0 != m_nCount);RemoveAt(m_nCount);}template<typename T>inline void DList<T>::RemoveAll(){int i;int nCount;Node<T> *pTmpNode;nCount = m_nCount;for (i = 0; i < nCount; ++i){pTmpNode = m_pNodeHead->next;delete m_pNodeHead;m_pNodeHead = pTmpNode;}m_pNodeHead=NULL;m_pNodeTail=NULL;m_nCount = 0;}template<typename T>inline void DList<T>::SetAt(const int pos, T data){ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}pTmpNode->data = data;}template<typename T>inline int DList<T>::Find(const T data) const{int i;int nCount;Node<T> *pTmpNode = m_pNodeHead;nCount = m_nCount;for (i = 0; i < nCount; ++i){if (data == pTmpNode->data)return i + 1;pTmpNode = pTmpNode->next;}return 0;}/*判断链表是否有环,如果有环则返回环的首结点位置,否则返回0*/ template<typename T>inline int DList<T>::FindCircle() const{if(0==m_nCount) { return 0; } Node<T>* p1=m_pNodeHead; Node<T>* p2=m_pNodeHead; /*判断链表是否有环,当p1=p2时说明链表有环,程序跳出循环。如果p2一直走到链表尽头则说明没有环。*/ do{ if(p1!=NULL&&p2!=NULL&&p2->next!=NULL) { p1=p1->next; p2=p2->next->next; } else return 0; } while(p1!=p2); /*求出环的起点节点,并将其返回*/ p2=m_pNodeHead; while(p1!=p2) { p1=p1->next; p2=p2->next; } int i; p2=m_pNodeHead; for(i=1;i<=m_nCount;i++) { if(p1==p2) break; p2=p2->next; } return i; }/*判断两个链表是否交叉,如果交叉返回首个交叉节点位置(在本链表中的位置,而不是testlist中的位置),否则返回0。 假定:这两个链表本身均无环*/ template<typename T>inline int DList<T>::FindCross(DList& testlist){if(0==m_nCount||0==testlist.m_nCount) { return 0; } if(FindCircle()||testlist.FindCircle()) { return 0; } /*将第二个链表接在第一个链表后面*/ Node<T>* pTail=m_pNodeHead; for(int i=1;i<m_nCount;i++) { pTail=pTail->next; } pTail=testlist.m_pNodeHead; m_nCount+=testlist.m_nCount; int i=FindCircle(); pTail=NULL; m_nCount-=testlist.m_nCount; return i; }//get the data at pos and let pos=pos+1 template<typename T>inline T& DList<T>::GetNext(int &pos){ASSERT(0 != m_nCount);ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}++pos;return pTmpNode->data;}//get the data at pos and let pos=pos-1template<typename T>inline T& DList<T>::GetPrev(int &pos){ASSERT(0 != m_nCount);ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode = pTmpNode->next;}--pos;return pTmpNode->data;}#endif // __DOUBLE_LIST_H__
- C语言一个双向链表的实现
- C语言一个双向链表的实现
- C语言一个双向链表的实现
- C语言一个双向链表的实现
- C语言一个双向链表的实现
- 一个双向链表的实现
- 双向链表的一个C++实现
- 一个双向链表的实现
- 双向链表的一个C++实现
- 双向链表的实现 c
- c语言双向链表的实现
- 双向链表的C实现
- 双向链表的C实现
- c双向链表的实现
- 双向链表的C语言实现
- 双向链表的C实现
- 双向链表的C实现
- 【C++】双向链表的实现
- 枚举子集
- linux wireless
- 327 - Evaluating Simple C Expressions
- K好数
- web应用,javaEE企业级应用,如何严格区分?
- 双向链表的一个C++实现
- JAVA [ 集合 ]
- 439骑士走到固定位置最短路程
- 705 - Slash Maze
- 回溯走棋盘
- 翻译工作不好干
- 折半查找:有序表的查找
- Fedora 15五笔和拼音输入法安装及配置
- 写给过去,写给将来