数据结构之线性结构--双向循环链表

一、双向循环链表特点

双向循环链表的结构是在双向链表的基础上使头节点的前驱指针指向末尾的节点,而使末尾的节点的一个指针指向开始节点,形成一个循环结构。

双向循环链表在进行节点的删除的时候的操作:

双向循环链表在进行节点的插入时的操作:

二、双向循环链表的实现

AL_Node.h文件

#ifndef AL_NODE_INCLUDE
#define AL_NODE_INCLUDE

#include <windows.h>
template<typename T> class AL_ListCircuarDouble;

template<typename T>
class AL_Node
{
    //声明一个朋友类,使这个朋友类可以访问这个类的私有元素
    friend class AL_ListCircuarDouble<T>;
public:
    ~AL_Node();
private:
    AL_Node();
    AL_Node(const T &tTemplate);
    AL_Node(const AL_Node<T>& cAL_Node);
    T m_data;//存储数据
    AL_Node *m_pPre;//记录链表的头结点地址
    AL_Node *m_pNext; //指向下一个节点地址
};

template<typename T>
AL_Node<T>::AL_Node() :m_pPre(NULL), m_pNext(NULL)
{


}

template<typename T>
AL_Node<T>::AL_Node(const T &tTemplate) :m_pPre(NULL), m_pNext(NULL), m_data(tTemplate)
{

}

template<typename T>
AL_Node<T>::~AL_Node()
{
    m_pPre = NULL;
    m_pNext = NULL;
}

#endif // AL_NODE

AL_ListCircularDouble.h文件

#ifndef AL_LISTCIRCULARDOUBLE_INCLUDE
#define AL_LISTCIRCULARSINGLE_INCLUDE

#include <windows.h>
#include "AL_Node.h"

template<typename T>
class AL_ListCircuarDouble
{
public:
    static const DWORD LISTDOUBLE_POSITION_INVALID = 0xffffffff;
    AL_ListCircuarDouble();
    ~AL_ListCircuarDouble();
    //获取当前链表中节点的个数
    DWORD Length() const;
    //寻找当前值在节点中的位置
    DWORD Find(const T &tTemplate) const;
    //判断当前元素是否存在
    bool IsElement(const T& tTemplate) const;
    //插入元素
    bool Insert(DWORD dwIndex, const T& tTemplate);
    bool InsertBegin(const T& tTemplate);
    bool InsertEnd(const T& tTemplate);
    //移除元素
    bool Remove(const T& tTemplate);
    //判断链表是否为空
    bool IsEmpty() const;
    //获取链表中的元素
    bool Get(T& tTypeOut, DWORD dwIndex) const;
    //修改链表中的元素值
    bool Set(T& tTypeOut, DWORD dwIndex, const T& tTemplate);
    //删除整个表中的节点
    void Clear();
private:
    //根据索引寻找链表中的节点
    AL_Node<T>* GetNodeByIndex(DWORD dwIndex) const;
    DWORD    m_dwSize;//记录当前链表中节点的个数
    AL_Node<T>* m_pHeader;//节点数据结构对象。
};



#endif

template<typename T>
inline AL_ListCircuarDouble<T>::AL_ListCircuarDouble():m_pHeader(NULL),m_dwSize(0x00)
{
    m_pHeader = new AL_Node<T>();
    m_pHeader->m_pPre = m_pHeader;
    m_pHeader->m_pNext = m_pHeader;
}

template<typename T>
inline AL_ListCircuarDouble<T>::~AL_ListCircuarDouble()
{
    Clear();
    if (m_pHeader!=NULL)
    {
        delete m_pHeader;
        m_pHeader = NULL;
    }

}

template<typename T>
inline DWORD AL_ListCircuarDouble<T>::Length() const
{
    return m_dwSize;
}

template<typename T>
inline DWORD AL_ListCircuarDouble<T>::Find(const T & tTemplate) const
{
    if (IsEmpty()==true)
    {
        return LISTDOUBLE_POSITION_INVALID;
    }
    AL_Node<T> *pMvoe = NULL;
    DWORD dwCount = 1;
    pMvoe = m_pHeader->m_pNext;
    while(pMvoe->m_pNext!=NULL)
    {
        if (pMvoe->m_data==tTemplate)
        {
            return dwCount - 1;
        }
        dwCount++;
        pMvoe = pMvoe->m_pNext;
    }

    if (pMvoe->m_data==tTemplate)
    {
        return dwCount - 1;
    }

    return LISTDOUBLE_POSITION_INVALID;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::IsElement(const T & tTemplate) const
{
    if (Find(tTemplate) == LISTDOUBLE_POSITION_INVALID);
    {
        return false;
    }
    return true;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::Insert(DWORD dwIndex, const T & tTemplate)
{
    if (dwIndex>Length())
    {
        return false;
    }

    AL_Node<T> *pInsert = new AL_Node<T>();
    pInsert->m_data = tTemplate;
    AL_Node<T> *pPer = NULL;

    if (dwIndex==0x00)
    {
        pPer = m_pHeader;
    }
    else
    {
        pPer = GetNodeByIndex(dwIndex - 1);
    }

    if (pPer==NULL)
    {
        return false;
    }

    if (dwIndex==Length())
    {
        pPer->m_pNext = pInsert;
        pInsert->m_pPre = pPer;
        pInsert->m_pNext = m_pHeader;
        m_pHeader->m_pPre = pInsert;
    }
    else
    {
        AL_Node<T> *IndexNode = pPer->m_pNext;
        if (IndexNode==NULL)
        {
            return false;
        }
        pPer->m_pNext = pInsert;
        pInsert->m_pPre = pPer;
        pInsert->m_pNext = IndexNode;
        IndexNode->m_pPre = pInsert;
    }

    m_dwSize++;
    return true;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::InsertBegin(const T & tTemplate)
{
    return Insert(0x00, tTemplate);
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::InsertEnd(const T & tTemplate)
{
    return Insert(Length(),tTemplate);
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::Remove(const T & tTemplate)
{
    if (IsEmpty()==true)
    {
        return false;
    }
    DWORD dwPosition = Find(tTemplate);
    if (dwPosition==LISTDOUBLE_POSITION_INVALID)
    {
        return false;
    }
    AL_Node<T> *pDelete =GetNodeByIndex(dwPosition);
    if (pDelete==NULL)
    {
        return false;
    }

    AL_Node<T> *pPer = NULL;
    if (dwPosition==0x00)
    {
        pPer= m_pHeader;
    }
    else
    {
        pPer = pDelete->m_pPre;
    }

    if (pPer==NULL)
    {
        return false;
    }

    pPer->m_pNext = pDelete->m_pNext;
    delete pDelete;
    pDelete = NULL;
    m_dwSize--;
    return true;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::IsEmpty() const
{
    //判断是否循环指向头结点。
    return (m_pHeader->m_pNext==m_pHeader)?true:false;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::Get(T & tTypeOut, DWORD dwIndex) const
{
    if (IsEmpty() == true)
    {
        return false;
    }

    if (dwIndex>Length()-1)
    {
        return false;
    }
    AL_Node<T> *pGet = GetNodeByIndex(dwIndex);
    if (pGet==NULL)
    {
        return false;
    }
    tTypeOut = pGet->m_data;
    return true;
}

template<typename T>
inline bool AL_ListCircuarDouble<T>::Set(T & tTypeOut, DWORD dwIndex, const T & tTemplate)
{
    if (IsEmpty()==true)
    {
        return false;
    }

    if (dwIndex>Length()-1)
    {
        return false;
    }
    AL_Node<T> *pSet = GetNodeByIndex(dwIndex);
    if (pSet==NULL)
    {
        return false;
    }
    tTypeOut = pSet->m_data;
    pSet->m_data = tTemplate;
    return true;
}

template<typename T>
inline void AL_ListCircuarDouble<T>::Clear()
{
    if (IsEmpty()==true)
    {
        return;
    }

    AL_Node<T> *pDelete = NULL;
    while (m_pHeader->m_pNext!=m_pHeader)
    {
        pDelete = m_pHeader->m_pNext;
        m_pHeader->m_pNext = pDelete->m_pNext;
        delete pDelete;
        pDelete = NULL;
    }
    m_dwSize = 0x00;
}

template<typename T>
inline AL_Node<T>* AL_ListCircuarDouble<T>::GetNodeByIndex(DWORD dwIndex) const
{
    if (dwIndex>Length()-1)
    {
        return NULL;
    }

    AL_Node<T> * pMove = NULL;
    DWORD dwCount = 1;
    pMove = m_pHeader->m_pNext;
    while (pMove->m_pNext!=m_pHeader)
    {
         if (dwCount-1==dwIndex)
         {
             return pMove;
         }
         dwCount++;
         pMove = pMove->m_pNext;
    }
    return pMove;
}

测试代码:


void ListCircularDoubleTest()
{
    AL_ListCircuarDouble<DWORD> clistCircuarDouble;
    bool bEmpty = clistCircuarDouble.IsEmpty();
    std::cout << bEmpty << std::endl;

    int arrays[15] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
    for (int  i = 0; i < 15; i++)
    {
     clistCircuarDouble.Insert(i, arrays[i]);
    }
    bEmpty = clistCircuarDouble.IsEmpty();
    DWORD blength = clistCircuarDouble.Length();
    std::cout << bEmpty << " " << blength << std::endl;

    bEmpty = clistCircuarDouble.Remove(6);
    blength = clistCircuarDouble.Length();
    std::cout << bEmpty << "  " << blength << std::endl;

    DWORD  sget, sset;
    clistCircuarDouble.Set(sset, 5, 123);
    clistCircuarDouble.Get(sget, 5);
    std::cout << sset << " " << sget << std::endl;

    DWORD  sfind = clistCircuarDouble.Find(5);
    DWORD sfind1 = clistCircuarDouble.Find(123);
    std::cout << sfind1 << " " << sfind << std::endl;
}

int main(int argc, char *argv[])
{
    ListCircularDoubleTest();
    getchar();
    return 0;
}

运行结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值