隊列(queue)是一種限定存取位置的線性變。他允許在表的一端插入,在另一端刪除。這個和計算機調度策略中的先來先服務FCFS(First Come/First Served)是一樣的。隊列中可以插入的一端為隊尾(rear),允許刪除的一端稱為隊頭(front)。
隊列也分為兩種,一種是用數組的存儲表示,一種是基於鏈表的存儲表示。
基於數組的存儲表示的隊列被稱為順序隊列。其數據成員包括,一維數組elements用來存儲數據,指針front和rear用來指示隊尾隊頭的位置,maxSize是數組的最大長度。
從上邊的圖可以看出來,rear指針到指到數組最后一位時就不能繼續往后添加元素,如果之前刪除過元素,front指針前還有空閑的空間未被使用,造成空間的浪費。所以,使隊列循環起來就可以使其最大限度的利用空間。
變成循環隊列,為了避免越界,每次添加新元素時,尾指針需要加一后對堆長取余
即 rear = (rear+1)%maxSize;
刪除元素也一樣
front = (front+1)%maxSize;
為了區別於空隊列,用(rear+1)%maxSize==front來判斷是否隊滿,即隊尾走到隊頭前一個位置即判定隊滿。再因為隊尾所指的空間為最后一個元素的下一個位置,所以循環隊列最多能存放maxSize-1個元素。
//queue.h
#ifndef _QUEUE_H
#define _QUEUE_H
#include<iostream>
using namespace std;
const int maxSize = 50;
template<class T>
class Queue
{
public:
Queue(){};
~Queue(){};
virtual bool EnQueue(const T& x) = 0;
virtual bool DeQueue(T& x) = 0;
virtual bool getFront(T& x) = 0;
virtual bool IsEmpty()const = 0;
virtual bool IsFull()const = 0;
virtual int getSize()const = 0;
};
#endif
//main.cpp
#include<assert.h>
#include"queue.h"
template<class T>
class SeqQueue;
template<class T>
ostream& operator<< (ostream& out, SeqQueue<T>& Q)//將友元函數聲明在前可以避免其警告友元函數未聲明
{
cout<<"front = "<<Q.front<<", rear = "<<Q.rear<<endl;
if(!Q.IsEmpty())
{
int i = Q.front;
while(i!=Q.rear)
{
cout<<Q.elements[i]<<" | ";
i = (++i)%maxSize;
}
}
return out;
}
template<class T>
class SeqQueue: public Queue<T>
{
private:
int rear, front;
T *elements;
int maxSize;
public:
SeqQueue(int sz=10);//構造函數
~SeqQueue(){delete[] elements;}//析構函數
bool EnQueue(const T& x);//入隊列
bool DeQueue(T& x);//出隊列
bool getFront(T& x);//找隊頭
bool IsEmpty()const{return (this->rear==this->front) ? true : false;}//判空
bool IsFull()const{return ((this->rear+1)%this->maxSize==this->front) ? true : false;}//判滿
int getSize()const{return(this->rear-this->front+this->maxSize)%this->maxSize;}//得隊長
friend ostream& operator<<<>(ostream& out, SeqQueue<T>& Q);
//void print();
};
/*template<class T>
void SeqQueue<T>::print()
{
if(!this->IsEmpty())
{
int i = this->front;
while(i!=this->rear)
{
cout<<this->elements[i]<<" | ";
i = (++i)/this->maxSize;
}
}
}*/
template<class T>
bool SeqQueue<T>::EnQueue(const T& x)
{
if(!this->IsFull())
{
this->elements[this->rear] = x;
this->rear = (this->rear+1)%this->maxSize;
return true;
}
return false;
}
template<class T>
bool SeqQueue<T>::DeQueue(T& x)
{
if(!this->IsEmpty())
{
x = this->elements[this->front];
this->front = (this->front+1)%this->maxSize;
return true;
}
return false;
}
template<class T>
bool SeqQueue<T>::getFront(T& x)
{
if(!this->IsEmpty())
{
x = this->elements[this->front];
return true;
}
return false;
}
template<class T>
SeqQueue<T>::SeqQueue(int sz):front(0),rear(0),maxSize(sz)
{
this->elements = new T[maxSize];
assert(this->elements!=NULL);
}
int main()
{
SeqQueue<int> Q(7);
for(int i=7; i>0; --i)
Q.EnQueue(i);
cout<<Q<<endl;//聲明友元函數並重載輸出運算符<<就可以用cout直接輸出對象
int q = 0;
for(int i=3; i>=0; --i)
Q.DeQueue(q);
cout<<Q<<endl;
cout<<"Size = "<<Q.getSize()<<endl;
return 0;
}
運行結果