1. 程式人生 > >筆記七:基於陣列的迴圈佇列的實現

筆記七:基於陣列的迴圈佇列的實現

定義佇列也是一種線性表。其特點是佇列的插入與刪除在兩端進行,是一個先進先出(FIFO)的線性表。插入元素的一端叫隊尾,刪除元素的一端叫隊首。

三種表現形式:

1、

公式1: location(i)=i

——佇列第i個元素對映到陣列中,即為下標為i的元素,i>=0。
這裡寫圖片描述

2、

公式2:location(i)=location(隊首元素)+i

——佇列第i個元素在陣列中的位置只與隊首元素有關,則刪除一個隊首元素時不需要吧元素左移,queueFront加1就好。因此可以解決1中的問題。
這裡寫圖片描述

3、

公式3:location(i)=(location(隊首元素)+i)% arrayLength

——把陣列視為一個環,則2中出現的空間利用率不高的問題可以解決。

這裡寫圖片描述

在1,2中queueFront=queueBack=-1,在3中對陣列下標求餘%,故初始狀態queueFront=queueBack=0,若對圖3中左上角陣列繼續插入一個元素D,假設可以插在下標為0處,則queueFront=queueBack,不能判斷此時佇列是空還是滿,因此應空餘一個空間給queueFront標識。即在初始化的空佇列中,插入的第一個元素位於佇列陣列下標為1的位置,而不是0。每次插入一個新元素,queueBack=(queueBack+1)% arrayLength,是考慮到迴圈插入陣列中。

程式碼:

#pragma warning(disable:4996)
#include<iostream>
using namespace std;

template<typename T>
class queue
{
public:
    virtual ~queue() {};
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual T& front() = 0; //返回頭元素的引用
    virtual T& back() = 0;  //返回尾元素的引用
virtual void pop() = 0; //刪除首元素 virtual void push(const T& theElement) = 0; //把元素加入隊尾 }; template<typename T> class arrayQueue : public queue<T> { public: arrayQueue(int initialCapacity = 10); ~arrayQueue() { delete[] que; } bool empty() const { return queueFront == queueBack; } int size() const; T& front(); T& back(); void pop(); void push(const T& theElement); private: T* que; int queueFront; //首元素前一位置的下標 int queueBack; //尾元素的下標 int arrayLength; }; template<typename T> arrayQueue<T>::arrayQueue(int initialCapacity) { if (initialCapacity < 0) { cout << "佇列容量必須不小於0!" << endl; exit(-1); } que = new T[initialCapacity]; queueFront = queueBack = 0; arrayLength = initialCapacity; } template<typename T> int arrayQueue<T>::size() const { if (queueBack >= queueFront) { return queueBack - queueFront; } else{ return arrayLength - queueFront - 1 + queueBack + 1; } } template<typename T> T& arrayQueue<T>::front() { if (queueBack == queueFront) { cout << "佇列為空,故不存在隊首元素!"; exit(-1); } return que[queueFront+1]; } template<typename T> T& arrayQueue<T>::back() { if (queueBack == queueFront) { cout << "佇列為空,故不存在隊尾元素!"; exit(-1); } return que[queueBack]; } template<typename T> void arrayQueue<T>::pop() { if (queueBack == queueFront) { cout << "佇列為空!"; return ; } queueFront = (queueFront + 1) % arrayLength; } template<typename T> void arrayQueue<T>::push(const T& theElement) { if ((queueBack + 1) % arrayLength == queueFront) //容量已滿,需擴充 { T* newArray = new T[arrayLength * 2]; //第一步,將從queueFront到arrayLength範圍內的元素進行復制 copy(que + queueFront + 1, que + arrayLength, newArray+1); //第二步,若queueBack < queueFront ,則進行剩餘元素的複製 if (queueBack<queueFront) copy(que, que + queueBack, newArray + 1 + arrayLength - queueFront - 1); //設定新的隊首和隊尾,隊的容量 queueFront = 0; queueBack = arrayLength -1; arrayLength = arrayLength * 2; delete[] que; que = newArray; } queueBack = (queueBack + 1) % arrayLength; //新的隊尾標識 que[queueBack] = theElement; } int main(int argc, char* argv[]) { arrayQueue<int> AQ(6); cout << "將元素5插入佇列中:" << endl; AQ.push(5); cout << "隊首元素:" << AQ.front() << endl; cout << "隊尾元素:" << AQ.back() << endl; cout << "隊總元素:" << AQ.size() << endl; cout << endl; AQ.push(4); AQ.push(3); AQ.push(2); AQ.push(1); cout << "將元素4,3,2,1依次插入佇列中:" << endl; cout << "隊首元素:" << AQ.front() << endl; cout << "隊尾元素:" << AQ.back() << endl; cout << "隊總元素:" << AQ.size() << endl; cout << endl; AQ.pop(); AQ.pop(); AQ.pop(); AQ.pop(); AQ.push(6); AQ.push(7); cout << "刪除4個隊首元素,插入2個新元素後:" << endl; cout << "隊首元素:" << AQ.front() << endl; cout << "隊尾元素:" << AQ.back() << endl; cout << "隊總元素:" << AQ.size() << endl; cout << endl; AQ.push(0); cout << "繼續插入元素0:" << endl; cout << "隊首元素:" << AQ.front() << endl; cout << "隊尾元素:" << AQ.back() << endl; cout << "隊總元素:" << AQ.size() << endl; return 0; }

執行:
這裡寫圖片描述