1. 程式人生 > >資料結構——迴圈佇列(順序佇列)模板類實現

資料結構——迴圈佇列(順序佇列)模板類實現

資料結構筆記3.3
順序佇列是用順序表實現的(即依託於陣列),這裡實現的是迴圈佇列,其實也可以不用迴圈,但是那樣的話,空間的利用效率就太低了,這就是”假溢位”問題,因為在陣列的前端可能還有空閒的位置(因為佇列中的資料是在動態變化的,可能出隊也可能入對)。
為了能夠充分利空間,所以用迴圈佇列,即在邏輯上把陣列的隊結構看成一個環。具體實現:實現的方式還是十分巧妙地,運用兩個指標和鍾運算(就是取模或是取餘運算)。
隊頭指標進1:front = (front + 1) % maxSize;
隊尾指標進1 : rear = (rear + 1) % maxSize;
上面兩個式子就是鍾運算在佇列資料操作時候的實現原理。
另外,在判斷佇列NULL與佇列FULL的時候會遇到混淆的問題,NULL的時候,在即rear == front ,但是由於是迴圈表,當表FULL的時候,兩者也是相等的,一種區分方式就是當rear檢測到其下一個就是front的時候作為佇列滿的依據,這樣就相當於佇列滿的時候也會有一個節點是空閒的。
好了,在編寫這個類的過程中,需要強調的就這幾個地方,下面貼出程式碼:
虛基類程式碼(此程式碼段放入queue.h當中,並在模板類程式碼中包含)

template<class T>
class Queue {
public:
    Queue(){}                               //建構函式
    ~Queue(){}                             //解構函式
    virtual bool EnQueue(const T & x) = 0;  //新元素x進入佇列
    virtual bool DelQueue(T & x) = 0;       //隊頭元素出佇列
    virtual bool getFront(T & x) = 0;       //讀取隊頭元素的值
virtual bool IsEmpty()const = 0; //判斷佇列是否為NULL virtual bool IsFull() const = 0; //判斷佇列是否已滿 virtual int getSize() const = 0; //求佇列元素的個數 };
模板class程式碼:
#include <iostream>
#include <cassert>
#include <cmath>
#include "queue.h"
using namespace std;
//順序佇列模板類定義(迴圈佇列)
template<class T> class SeqQueue : public Queue<T> { public: SeqQueue(int sz = 10); //建構函式 ~SeqQueue(); //解構函式 //若佇列不滿則將x進入佇列,否則溢位處理 bool EnQueue(const T & x); //若佇列不空則刪除隊頭元素x,並返回true,否則返回false bool DelQueue(T & x); //若佇列不空則函式返回隊頭元素並返回true,否則返回false bool getFront(T & x); //置空操作,隊頭指標與隊尾指標置0 void makeEmpty(); //判斷佇列是否為空,是則返回true否則返回false bool IsEmpty() const; //判斷佇列是否已滿,是返回true否則返回false bool IsFull() const; //求佇列元素的個數 int getSize() const; //輸出佇列元素,運算子過載函式呼叫 void output(ostream & out); protected: int rear, front; //隊尾與隊頭指標 T *elements; //存放佇列元素的陣列 int maxSize; //佇列最大可容納的元素個數 }; //函式定義 template<class T> SeqQueue<T>::SeqQueue(int sz) { //建立一個最大就有maxSzie個元素的空佇列 maxSize = sz; elements = new T[sz]; //開闢記憶體 assert(elements != NULL); //記憶體分配不成功的中斷處理 rear = front = 0; //初始化隊頭與隊尾指 } template<class T> SeqQueue<T>::~SeqQueue() { //解構函式,釋放程式中相應的資源 delete[] elements; } template<class T> bool SeqQueue<T>::EnQueue(const T & x) { //若佇列不滿則將x進入佇列,否則溢位處理 if (IsFull()) { //如果佇列已經滿,則返回false return false; } elements[rear] = x; rear = (rear + 1) % maxSize; //通過鍾運算實現元素的迴圈填充 return true; } template<class T> bool SeqQueue<T>::DelQueue(T & x) { //若佇列不空則刪除隊頭元素x,並返回true,否則返回false if (IsEmpty()) { return false; } x = elements[front]; front = (front + 1) % maxSize; return true; } template<class T> bool SeqQueue<T>::getFront(T & x) { //若佇列不空則函式返回隊頭元素並返回true,否則返回false if (IsEmpty()) { return false; } x = elements[front]; return true; } template<class T> bool SeqQueue<T>::IsEmpty() const { if (rear == front) { return true; } else { return false; } } template<class T> bool SeqQueue<T>::IsFull() const { if (fmod((rear + 1), maxSize) == front) { //如果rear的下一個節點與front相同則定義為佇列已滿 //從而區分佇列為NULL,即rear==front的情況 return true; //注意這個時候佇列中會有一個NULL的節點 } else { return false; } } template<class T> void SeqQueue<T>::makeEmpty() { //置NULL操作 rear = front = 0; } template<class T> int SeqQueue<T>::getSize() const { //求佇列元素的個數 return (rear - front + maxSize) % maxSize; } template<class T> void SeqQueue<T>::output(ostream & out) { for (int i = front; i != rear; i = (i + 1) % maxSize) { out << elements[i] << ' '; } cout << endl; } template<class T> ostream & operator << (ostream & out, SeqQueue<T> & SQ) { //過載插入運算子 SQ.output(out); return out; }

Main測試程式碼:

int main()
{
    SeqQueue<int> squeue;               //定義迴圈佇列物件
    squeue.EnQueue(1);                  //進隊與出隊測試
    squeue.EnQueue(2);
    squeue.EnQueue(3);
    squeue.EnQueue(4);
    squeue.EnQueue(5);
    cout << squeue;
    int outQueVal_1, outQueVal_2;
    squeue.DelQueue(outQueVal_1);
    squeue.DelQueue(outQueVal_2);
    cout << squeue;

    int quFrontVal = 0;
    squeue.getFront(quFrontVal);        //提取隊頭資料測試
    cout << quFrontVal << endl;

    squeue.makeEmpty();                 //設定NULL與測試NULL測試
    if (squeue.IsEmpty()) {
        cout << "佇列為NULL" << endl;
    }
    else {
        cout << "佇列非空" << endl;
    }

    squeue.EnQueue(2);                  //取佇列大小測試
    squeue.EnQueue(3);
    squeue.EnQueue(4);
    cout << squeue.getSize() << endl;

    system("pause");
    return 0;
}

執行結果:
這裡寫圖片描述