筆記七:基於陣列的迴圈佇列的實現
阿新 • • 發佈:2018-12-25
定義:佇列也是一種線性表。其特點是佇列的插入與刪除在兩端進行,是一個先進先出(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;
}
執行: