双向链表的一个C++实现

代码很简洁明了,自己转载后以便复习之用!

原文地址:http://blog.csdn.net/kevinzhangyang/article/details/6637359

/*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_pNodeTail   
    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(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_pNodeTail   
    if (NULL == pNewNode->next)  
    {  
        m_pNodeTail = pNewNode;  
    }  
  
    nRetPos = pos;  
  
    ++m_nCount;  
    return nRetPos;  
}  
//insert data after pos   
template<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_pNodeTail   
    if(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 pos   
template<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-1   
template<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__



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值