单链表的一个C++实现

来源:互联网 发布:如何发起淘宝众筹项目 编辑:程序博客网 时间:2024/05/19 10:53
 

下面是单链表的一个C++实现,参考了《数据结构与算法分析C语言版》及不少牛人的分析总结,在此一并感谢了。在VC2005上经反复验证试验,结果非常不错。但可能还有不少bug,如果发现bug, 请告诉我一下。

  注意:单链表及双向及循环链表均不适用表头(即哑节点,dummy node), 即m_pNodeHead指针指向链表的第一个真正节点。

/*slist.h*/#include <assert.h>#include <crtdbg.h>template<typename T>//class T must have default constructorclass Node{public:T data;Node<T> *next;Node() : data(T()), next(NULL) {}Node(const T &initdata) : data(initdata), next(NULL) {}Node(const T &initdata, Node<T> *p) : data(initdata), next(p) {}};template<typename T>class SList{public:SList();SList(const T &initdata);SList(const SList<T>& other);SList<T>& operator=(const SList<T>& other);~SList();public:void    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(SList& testlist);protected:int m_nCount;Node<T> *m_pNodeHead;};template<typename T>inline SList<T>::SList() : m_nCount(0), m_pNodeHead(NULL){}template<typename T>inline SList<T>::SList(const T &initdata) : m_nCount(0), m_pNodeHead(NULL){AddHead(initdata);}template<typename T>inline SList<T>::SList(const SList<T>& other) : m_nCount(0), m_pNodeHead(NULL){if(other.m_nCount>0){for(int i=1;i<=other.m_nCount;i++){AddTail(other.GetAt(i));}}}template<typename T>inline SList<T>& SList<T>::operator=(const SList<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 SList<T>::~SList(){RemoveAll();}//reverse the listtemplate<typename T>inline void SList<T>::Invert(){if(m_nCount<=1) return;Node<T> *curNod,*preNod,*nextNod;curNod=m_pNodeHead;preNod=NULL;for(int i=1;i<=m_nCount;i++){nextNod=curNod->next;curNod->next=preNod;preNod=curNod;curNod=nextNod;}    m_pNodeHead=preNod;    return;}template<typename T>inline int SList<T>::IsEmpty() const{return 0 == m_nCount;}template<typename T>inline int SList<T>::AddHead(const T data){/*Node<T> *pNewNode;try{pNewNode = new Node<T>;}catch (std::bad_alloc&) {return 0;}pNewNode->data = data;pNewNode->next = m_pNodeHead;m_pNodeHead = pNewNode;++m_nCount;return 1;*/return InsertBefore(1,data);}template<typename T>inline int SList<T>::AddTail(const T data){return InsertAfter(GetCount(), data);}// if success, return the position of the new node.// if fail, return 0.template<typename T>inline int SList<T>::InsertBefore(const int pos, const T data){int i;int nRetPos;Node<T> *pTmpNode1;Node<T> *pTmpNode2;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->next = NULL;m_pNodeHead = 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->next = m_pNodeHead;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.pTmpNode1 = m_pNodeHead;for (i = 1; i < pos; ++i){pTmpNode2 = pTmpNode1;pTmpNode1 = pTmpNode1->next;}pNewNode->next = pTmpNode1;pTmpNode2->next = pNewNode;nRetPos = pos;++m_nCount;return nRetPos;}// if success, return the position of the new node.// if fail, return 0.template<typename T>inline int SList<T>::InsertAfter(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->next = NULL;m_pNodeHead = 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;pTmpNode->next = pNewNode;nRetPos = pos + 1;++m_nCount;return nRetPos;}template<typename T>inline int SList<T>::GetCount() const{return m_nCount;}template<typename T>inline void SList<T>::RemoveAt(const int pos){ASSERT(1 <= pos && pos <= m_nCount);int i;Node<T> *pTmpNode1;Node<T> *pTmpNode2;pTmpNode1 = m_pNodeHead;// head node?if (1 == pos){m_pNodeHead = m_pNodeHead->next;delete pTmpNode1;--m_nCount;return;}for (i = 1; i < pos; ++i){// we will get the previous node of the target node after// the for loop finished, and it would be stored into pTmpNode2pTmpNode2 = pTmpNode1;pTmpNode1 = pTmpNode1->next;}pTmpNode2->next = pTmpNode1->next;delete pTmpNode1;--m_nCount;}template<typename T>inline void SList<T>::RemoveHead(){ASSERT(0 != m_nCount);RemoveAt(1);}template<typename T>inline void SList<T>::RemoveTail(){ASSERT(0 != m_nCount);RemoveAt(m_nCount);}template<typename T>inline void SList<T>::RemoveAll(){int i;int nCount;Node<T> *pTmpNode;nCount = m_nCount;if(nCount==0){return;}for (i = 0; i < nCount; ++i){pTmpNode = m_pNodeHead->next;delete m_pNodeHead;m_pNodeHead = pTmpNode;}m_pNodeHead=NULL;m_nCount = 0;}template<typename T>inline T& SList<T>::GetTail(){ASSERT(0 != m_nCount);int i;int nCount;Node<T> *pTmpNode = m_pNodeHead;nCount = m_nCount;for (i = 1; i < nCount; ++i){pTmpNode = pTmpNode->next;}return pTmpNode->data;}template<typename T>inline T SList<T>::GetTail() const{ASSERT(0 != m_nCount);int i;int nCount;Node<T> *pTmpNode = m_pNodeHead;nCount = m_nCount;for (i = 1; i < nCount; ++i){pTmpNode = pTmpNode->next;}return pTmpNode->data;}template<typename T>inline T& SList<T>::GetHead(){ASSERT(0 != m_nCount);return m_pNodeHead->data;}template<typename T>inline T SList<T>::GetHead() const{ASSERT(0 != m_nCount);return m_pNodeHead->data;}template<typename T>inline T& SList<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 SList<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 void SList<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 SList<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 SList<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 SList<T>::FindCross(SList& 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;}#endif 
原创粉丝点击