1. 程式人生 > >【C++】容器介面卡實現佇列Queue的各種功能(入隊、出隊、判空、大小、訪問所有元素等)

【C++】容器介面卡實現佇列Queue的各種功能(入隊、出隊、判空、大小、訪問所有元素等)

介面卡:

將一個通用的容器轉換為另外的容器,所謂的容器,指的是存放資料的器具,像我們知道的順序表和連結串列都是容器Container。舉個例子解釋一下吧,我們的電壓都是220v,而像充電線就起到轉換到合適的電壓的作用。而這裡,我們的主角就是將通用的連結串列結構轉換為來實現佇列Queue這一資料結構,(意思就是,連結串列還可以去實現其他的資料結構)。

線上性表中,分為連結串列和順序表,我們知道其中的差別:

連結串列:節點靈活,使得插入刪除元素方便靈活,但是對於單鏈表若有節點指標_head、_tail,查詢元素較為麻煩,需要遍歷。

順序表:開闢一塊連續的記憶體空間,查詢元素方便,通過指標或者下標來訪問。插入或者刪除元素呢,又較為複雜,插入時需要將後面的元素挨著挨著全部後移,刪除元素後又需要將後面的元素全部前移。

針對佇列Queue模型,我們知道它是尾插頭刪、先進先出的特點。因此我針對以上原因選用連結串列結構來實現佇列Queue。可以參照下圖:

wKiom1bo06nSvSW8AAAYVK-E-CQ155.png

程式碼如下:

#include<iostream>
using namespace std;
#include<assert.h>

template<class T>
struct ListNode
{
    ListNode(const T& x)
    :_next(NULL)
    , _prev(NULL)
    , _data(x)
    {}

    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;
};

template<class T>
class List
{
public:
    List()
        :_head(NULL)
        , _tail(NULL)
    {}

    List(const List<T>& l)
    {
        ListNode<T>* cur = l._head;
        while (cur)
        {
            this->PushBack(cur->_data);
            cur = cur->_next;
        }
    }

    List<T>& operator=(const List<T>& l)
    {
        //先刪除節點,再插入節點
        if (&s != this)
        {
            ListNode<T>* pcur = _head;
            while (pcur)
            {
                ListNode<T>* del = pcur;
                pcur = pcur->_next;
                delete del;
                del = NULL;
            }

            ListNode<T>* cur = _head;
            while (cur)
            {
                this->PushBack(cur->_data);
                cur = cur->_next;
            }
        }
        return *this;
    }

    ~List()//一個節點一個節點的刪除
    {
        ListNode<T>* cur = _head;
        while (cur)
        {
            ListNode<T>* del = cur;
            cur = cur->_next;
            delete del;
            del = NULL;
        }
    }

    void PushBack(const T& x);
    void PopBack();
    void PopFront();
    void PrintList();
    void Reverse();
    size_t Length();    

public:
    ListNode<T>* _head;
    ListNode<T>* _tail;
};


//尾插
template<class T>
void List<T>::PushBack(const T& x)
{
    //分析:分為兩種情況:無節點、有節點
    if (_head == NULL)
    {
        _head = _tail = new ListNode<T>(x);
    }
    else
    {
        ListNode<T>* cur = new ListNode<T>(x);
        _tail->_next = cur;
        cur->_prev = _tail;
        _tail = cur;
        _tail->_next = NULL;
    }
}

//尾刪
template<class T>
void List<T>::PopBack()
{
    //分析:分為三種情況:無節點、一個節點、多個節點
    if (_head == _tail)
    {
        if (_head == NULL)
        {
            return;
        }
        else
        {
            delete _head;
            _head = _tail = NULL;
        }
    }
    else
    {
        ListNode<T>* prev = _tail->_prev;
        delete _tail;
        _tail = NULL;
        _tail = prev;
        _tail->_next = NULL;
    }
}

//頭刪
template<class T>
void List<T>::PopFront()
{
    if (_head == _tail)
    {
        if (_head == NULL)
        {
            return;
        }
        delete _head;
        _head = _tail = NULL;
    }
    else
    {
        ListNode<T>* cur = _head;
        ListNode<T>* del = _head;    
        _head = cur->_next;
        delete del;
        del = NULL;        
        _head->_prev = NULL;
    }
    
}

//逆置
template<class T>
void List<T>::Reverse()
{
    //分析:從兩頭開始走,交換資料(分奇數個數據和偶數個數據)
    ListNode<T>* begin = _head;
    ListNode<T>* end = _tail;
    while (!((begin == end) || end->_next == begin))
    {
        swap(begin->_data, end->_data);
        begin = begin->_next;
        end = end->_prev;
    }
}

//長度
template<class T>
size_t List<T>::Length()
{
    ListNode<T>* cur = _head;
    int count = 0;
    while (cur)
    {
        ++count;
        cur = cur->_next;
    }
    return count;
}


//列印
template<class T>
void List<T>::PrintList()
{
    ListNode<T>* cur = _head;
    while (cur)
    {
        cout << cur->_data << "->";
        cur = cur->_next;
    }
    cout << "NULL" << endl;
}

template<class T, template<class> class Container = List>    //預設形式
class Queue
{
public:
    //入隊
    void Push(const T& x)
    {
        _con.PushBack(x);
    }

    //出隊
    void Pop()
    {
        _con.PopFront();
    }

    //大小
    size_t Size()
    {
        return _con.Length();
    }

    //判空
    bool Empty()
    {
        return Size() == 0;
    }

    //隊頭
    T& Front()
    {
        size_t size = Size();
        assert(size > 0);
        return _con._head->_data;
    }

    //隊尾
    T& Back()
    {
        size_t size = Size();
        assert(size > 0);
        return _con._tail->_data;
    }

protected:
    Container<T> _con;
};


//佇列的測試函式
void TestQueue()
{
    Queue<int, List> q1;
    //Queue<int> q1;
    q1.Push(1);
    q1.Push(2);
    q1.Push(3);
    q1.Push(4);
    q1.Push(5);

    //訪問佇列所有元素(佇列是插尾刪頭)
    while (!q1.Empty())
    {
        cout<< q1.Front() << "  ";
        q1.Pop();
    }
}


int main()
{
    TestQueue();
    system("pause");
    return 0;
}