欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++——实现双向循环链表(带头结点)

程序员文章站 2024-03-22 11:20:40
...

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
简单的画一个双向循环简易图:
C++——实现双向循环链表(带头结点)

下面就用C++实现一下基本操作
当然也有 C 语言 版的,只是单链表操作
https://blog.csdn.net/Paranoid_cc/article/details/79707761

先分开写吧
1、四个重要的函数:构造函数、拷贝构造函数、赋值运算符重载、析构函数。

//构造函数
    List(size_t n,const DataType& data)
    {
        _CreateHead();
        for (size_t i = 0; i < n; ++i)
            PushBack(data);
    }

    List(DataType* first, DataType* last)
    {
        _CreateHead();
        while (first != last)
            PushBack(*first++);
    }

//拷贝构造函数
    List(const List& L)
    {
        _pHead = new Node();
        _pHead->_pNext = _pHead;
        _pHead->_pPre = _pHead;

        Node* pCur = L._pHead->_pNext;
        while (pCur != L._pHead)
        {
            this->PushBack(pCur->_data);
            pCur = pCur->_pNext;
        }
    }

//赋值运算符重载
    List& operator=(const List& s)
    {
        if (this != &s)
        {
            this->Clear();
            Node* pCur = s._pHead->_pNext;
            while (pCur != s._pHead)
            {
                this->PushBack(pCur->_data);
                pCur = pCur->_pNext;
            }
        }
        return *this;
    }

//析构函数
    ~List()
    {
        Clear();
        delete _pHead;
        _pHead = NULL;
    }

2、对链表的数据的操作(删除和插入)

//尾插
    void PushBack(const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pPre = _pHead->_pPre;
        pNewNode->_pNext = _pHead;
        _pHead->_pPre = pNewNode;
        pNewNode->_pPre->_pNext = pNewNode;
    }

//尾删
    void PopBack()
    {
        if (Empty())
            return;
        Node* pDelNode = _pHead->_pPre;
        pDelNode->_pPre->_pNext = _pHead;
        _pHead->_pPre = pDelNode->_pPre;

        delete pDelNode;
    }

    //头插
    void PushFront(const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pNext = _pHead->_pNext;
        pNewNode->_pPre = _pHead;
        _pHead->_pNext = pNewNode;
        pNewNode->_pNext->_pPre = pNewNode;
    }

    //头删
    void PopFront()
    {
        if (Empty())
            return;
        Node* pDelNode = _pHead->_pNext;
        _pHead->_pNext = pDelNode->_pNext;
        pDelNode->_pNext->_pPre = _pHead;
        delete pDelNode;
    }

    //任意位置插入
    Node* Insert(Node* pos, const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pNext = pos;
        pNewNode->_pPre = pos->_pPre;
        pNewNode->_pPre->_pNext = pNewNode;
        pos->_pPre = pNewNode;

        return pNewNode;
    }

    //任意位置删除
    Node* Erase(Node* pos)
    {
        if (NULL == pos || pos == _pHead)
            return NULL;

        Node* ret = pos->_pNext;
        pos->_pPre->_pNext = pos->_pNext;
        pos->_pNext->_pPre = pos->_pPre;

        delete pos;
        return ret;
    }

3、对链表空间的操作

//链表的大小
size_t Size()const
    {
        Node* pCur = _pHead->_pNext;
        size_t count = 0;
        while (pCur != _pHead)
        {
            count++;
            pCur = pCur->_pNext;
        }
        return count;
    }

    //判空
    bool Empty()const
    {
        return _pHead->_pNext == _pHead;
    }

    //改变链表的大小
    void ReSize(size_t newSize, const DataType& data = DataType())
    {
        int gap = newSize - Size();
        if (gap > 0)//链表元素增多了 
        {
            while (gap--)
                PushBack(data);//尾插
        }
        else
        {
            while (gap++)//链表元素减少了
                PopBack();
        }
    }

下面给出完成的操作代码以及测试代码和结果图

#define _CRT_SECURE_NO_WARNINGS
#define NULL 0
#include<iostream>
#include<string.h>
#include<assert.h>
using namespace std;

//双向循环链表(带头结点)
typedef int DataType;
struct Node
{
    Node* _pNext;
    Node* _pPre;
    DataType _data; 

    //构造函数
    Node(const DataType& data = DataType())
        :_pNext(NULL)
        , _pPre(NULL)
        , _data(data)
    {}
};

class List
{
publicList()
    {
        _CreateHead();
    }

    //构造函数
    List(size_t n,const DataType& data)
    {
        _CreateHead();
        for (size_t i = 0; i < n; ++i)
            PushBack(data);
    }

    List(DataType* first, DataType* last)
    {
        _CreateHead();
        while (first != last)
            PushBack(*first++);
    }

    //拷贝构造函数
    List(const List& L)
    {
        _pHead = new Node();
        _pHead->_pNext = _pHead;
        _pHead->_pPre = _pHead;

        Node* pCur = L._pHead->_pNext;
        while (pCur != L._pHead)
        {
            this->PushBack(pCur->_data);
            pCur = pCur->_pNext;
        }
    }

    //赋值运算符重载
    List& operator=(const List& s)
    {
        if (this != &s)
        {
            this->Clear();
            Node* pCur = s._pHead->_pNext;
            while (pCur != s._pHead)
            {
                this->PushBack(pCur->_data);
                pCur = pCur->_pNext;
            }
        }
        return *this;
    }

    //析构函数
    ~List()
    {
        Clear();
        delete _pHead;
        _pHead = NULL;
    }

    //尾插
    void PushBack(const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pPre = _pHead->_pPre;
        pNewNode->_pNext = _pHead;
        _pHead->_pPre = pNewNode;
        pNewNode->_pPre->_pNext = pNewNode;
    }

    //尾删
    void PopBack()
    {
        if (Empty())
            return;
        Node* pDelNode = _pHead->_pPre;
        pDelNode->_pPre->_pNext = _pHead;
        _pHead->_pPre = pDelNode->_pPre;

        delete pDelNode;
    }

    /*
    void PushBack(const DataType& data)//尾插
    {
        Node* pNewNode = new Node(data);
        if (NULL == _pHead)
        {
            _pHead = pNewNode;
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
        }
        else
        {
            Node* pTail = _pHead->_pPre;
            pTail->_pNext = pNewNode;
            pNewNode->_pPre = pTail;
            pNewNode->_pNext = _pHead;
            _pHead->_pPre = pNewNode;
        }
    }

    void PopBack()//尾删
    {
        if (NULL == _pHead)//链表为空
            return;
        else if (_pHead->_pNext == _pHead)//只有一个结点
        {
            delete _pHead;
            _pHead = NULL;
        }
        else//有多个结点
        {
            Node* pPreTail = _pHead->_pPre->_pPre;
            delete pPreTail;
            pPreTail->_pNext = _pHead;
            _pHead->_pPre = pPreTail;
        }
    }
    */

     //头插
    void PushFront(const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pNext = _pHead->_pNext;
        pNewNode->_pPre = _pHead;
        _pHead->_pNext = pNewNode;
        pNewNode->_pNext->_pPre = pNewNode;
    }

    //头删
    void PopFront()
    {
        if (Empty())
            return;
        Node* pDelNode = _pHead->_pNext;
        _pHead->_pNext = pDelNode->_pNext;
        pDelNode->_pNext->_pPre = _pHead;
        delete pDelNode;
    }

    //任意位置插入
    Node* Insert(Node* pos, const DataType& data)
    {
        Node* pNewNode = new Node(data);
        pNewNode->_pNext = pos;
        pNewNode->_pPre = pos->_pPre;
        pNewNode->_pPre->_pNext = pNewNode;
        pos->_pPre = pNewNode;

        return pNewNode;
    }

    //任意位置删除
    Node* Erase(Node* pos)
    {
        if (NULL == pos || pos == _pHead)
            return NULL;

        Node* ret = pos->_pNext;
        pos->_pPre->_pNext = pos->_pNext;
        pos->_pNext->_pPre = pos->_pPre;

        delete pos;
        return ret;
    }

    size_t Size()const
    {
        Node* pCur = _pHead->_pNext;
        size_t count = 0;
        while (pCur != _pHead)
        {
            count++;
            pCur = pCur->_pNext;
        }
        return count;
    }

    bool Empty()const
    {
        return _pHead->_pNext == _pHead;
    }

    void ReSize(size_t newSize, const DataType& data = DataType())
    {
        int gap = newSize - Size();
        if (gap > 0)//链表元素增多了 
        {
            while (gap--)
                PushBack(data);//尾插
        }
        else
        {
            while (gap++)//链表元素减少了
                PopBack();
        }
    }

    //取出链表第一个元素的数据
    DataType& Front()
    {
        assert(!Empty());
        return  _pHead->_pNext->_data;
    }
    const DataType& Front()const
    {
        assert(!Empty());
        return  _pHead->_pNext->_data;
    }

    DataType& Back()
    {
        assert(!Empty());
        return _pHead->_pPre->_data;
    }
    const DataType& Back() const
    {
        assert(!Empty());
        return _pHead->_pPre->_data;
    }

    void Clear()
    {
        Node* pCur = _pHead->_pNext;
        while (pCur != _pHead)
        {
            pCur = Erase(pCur);
        }
    }

private:
    void _CreateHead()
    {
        _pHead = new Node;
        _pHead->_pNext = _pHead;
        _pHead->_pPre = _pHead;
    }

    //打印函数
    friend ostream& operator<<(ostream& _cout, const List& l)
    {
        Node* pCur = l._pHead->_pNext;
        while (pCur != l._pHead)
        {
            _cout << pCur->_data << " ";
            pCur = pCur->_pNext;
        }
        return _cout;
    }

private:
    Node* _pHead;
};

void TestList()
{
    List l1;
    List l2(10,5);
    cout << l2 << endl;

    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    List l3(array, array + sizeof(array) / sizeof(DataType));
    cout << l3.Size() << endl;
    cout << l3 << endl;
    cout << l3.Front() << endl;
    cout << l3.Back() << endl;

    l3.ReSize(5);
    cout << l3.Size() << endl;
    cout << l3 << endl;
    cout << l3.Front() << endl;
    cout << l3.Back() << endl;

    l3.ReSize(15,6);
    cout << l3.Size() << endl;
    cout << l3 << endl;
    cout << l3.Front() << endl;
    cout << l3.Back() << endl;
}

int main()
{
    TestList();
    return 0;
}

结果图
C++——实现双向循环链表(带头结点)

后面会发出C++实现的动态顺序表的操作