一、基础知识
队列(Queue)是一种限定存取位置的线性表。它只允许在表的一端插入,而在另一端删除。允许插入的一端称为队尾(rear),允许删除的一端叫做队头(front)。每次在队尾加入新元素,加入称为进队,删除称为出队。
队列的这种特性正好与栈相反,叫做先进先出(FIFO,First In First Out)。队列的存储表示也有两种方式:顺序方式和链式方式
二、循环队列
队列的顺序存储方式是利用一维数组存储的。有两个指针front和rear,分别指示队列的队头元素和队尾元素,在此约定:front指示队头元素所在地,rear指示队尾元素所在地的后一位置;
初始时,队列设为空,设front=rear=0.当要添加一个元素到队列时,将新元素添加到rear所指的位置,再让队尾指针加1。当要头元素出队时,先取队头front所指元素,再把队头指针front加1;
判断循环队列满的条件是:(rear+1)%maxSize==front;
判断循环队列空的条件是:rear==front
求队列的长度:(rear-front+maxSize)%maxSize
注:上述表述方式,实际上有一个空间是利用不到的,假如当maxSize是100,实际上的利用空间是99%,当其是1000,实际上的利用空间是99.9%;但是这种浪费是很小的
具体实现代码:
#ifndef GUARD_SEQQUEUE_h
#define GUARD_SEQQUEUE_h
#include<iostream>
#include<cassert>
template<class T>
class SeqQueue{
public:
explicit SeqQueue(int x=18);
virtual ~SeqQueue(){
delete []elems;
}
//判断队空
bool IsEmpty()const{
return rear==front;
}
//判断队满
bool IsFull()const{
return (rear+1)%maxSize==front;
}
//元素个数
int GetLength()const{
return (rear-front+maxSize)%maxSize;
}
//入队
void EnQueue(const T& e);
//出队
T DelQueue();
//取对头元素
T GetFront();
//清空队列
void Clear(){
front=rear=0;
}
private:
int front;
int rear;
int maxSize;
T* elems;
};
template<class T>
SeqQueue<T>::SeqQueue(int x){
maxSize=x;
front=0;
rear=0;
elems=new T[maxSize];
}
template<class T>
void SeqQueue<T>::EnQueue(const T& e){
assert(!IsFull());
elems[rear]=e;
rear=(rear+1)%maxSize;
}
//
template<class T>
T SeqQueue<T>::DelQueue(){
assert(!IsEmpty());
T temp=elems[front];
front=(front+1)%maxSize;
return temp;
}
//
template<class T>
T SeqQueue<T>::GetFront(){
assert(!IsEmpty());
return elems[front];
}
#endif
#include"SeqQueue.h"
#include<iostream>
using namespace std;
int main(){
int i;
SeqQueue<char> que; //缺省为18元素队列,可用17
char str1[]="abcdefghijklmnop";//17个元素,包括串结束符
que.Clear();
for(i=0;i<17;i++) que.EnQueue(str1[i]);
if(que.IsFull()) cout<<"队满";
cout<<"共有元素:"<<que.GetLength()<<endl;
for(i=0;i<17;i++) cout<<que.DelQueue(); //先进先出
cout<<endl;
if(que.IsEmpty()) cout<<"队空";
cout<<"共有元素:"<<que.GetLength()<<endl;
return 0;
}