简言之,队列具有以下特点:
- 初始值front=rear=-1
- front指向第一个数据的前面,rear直接指向最后一个数据
- 判断队列为空的条件是front==rear
- 判断队列满的条件是rear==maxSize-1
- 有效数据个数为rear-front
- 入队时先增加rear,再在rear处插入数据
- 出队时先增加front,再在front处取出数据
在队尾添加元素,在队首删除元素(排队,先到先出)
循环队列
基本思路
数组+指针实现,需要指定队列长度。
前期准备:
1.需要两个指针:队首(front)、队尾(rear)指针
front永远指向队头元素前一位置,front之后才是第一结点
2.循环链接首尾
队列长度:Qsize
(rear+1)%Qsize==front
3.通过C++类实现功能封装
class CirQueue{
public:
CirQueue();
~CirQueue();
void add(int x); //入队
int chu(); //出队
int get(); //取队首元素
int empty(); //判空
void print();
private:
int front ,rear; //front永远指向队头元素前一位置。front之后才是第一结点
int data[Qsize]; //数组存储循环队列
};
基本操作思路:
1.添加在队尾进行,rear后移之后加数据
2.出队在队首进行,front后移以使第一结点后移
注意:
1.队空:前、后指针相等.即:front==rear
2.队满:牺牲一个空间 .即:(rear+1)%Qsize==front
功能实现
构造函数
CirQueue::CirQueue(){
front=rear=-1; //front 指向队列元素前
}
入队
void CirQueue::add(int x){
//先判断队满:牺牲一个空间
if((rear+1)%Qsize==front) throw"队满" ;
//在队尾加入元素
rear= (rear+1)%Qsize;
//尾指针后移,在新位置插入元素
data[rear]=x;
}
出队
int CirQueue::chu(){
//队首出队
if(front==rear) throw"队空!";
front=(front+1)%Qsize; //front最初指向队头元素前一位置。头指针后移,使得原来的的队首元素出队
return data[front];
}
判空
int CirQueue::empty(){
//队空条件:前、后指针相等
if(front==rear) return 1;
else return 0;
}
取队首元素
int CirQueue::get(){
if(front==rear) throw"队空!";
return data[(front+1)%Qsize]; //取队首元素
}
遍历队列
void CirQueue::print(){
cout<<"当前队列中的所有元素为:";
for(int i=front+1;i<=rear;i++) cout<<data[i]<<" ";
cout<<endl;
}
完整代码
#include<iostream>
using namespace std;
const int Qsize=10;
class CirQueue{
public:
CirQueue();
~CirQueue();
void add(int x); //入队
int chu(); //出队
int get(); //取队首元素
int empty(); //判空
void print();
private:
int front ,rear; //front永远指向队头元素前一位置。front之后才是第一结点
int data[Qsize]; //数组存储循环队列
};
CirQueue::CirQueue(){
front=rear=-1; //front 指向队头元素前一位置。
}
CirQueue::~CirQueue(){}
void CirQueue::add(int x){
//先判断队满:牺牲一个空间
if((rear+1)%Qsize==front) throw"队满" ;
//在队尾加入元素
rear= (rear+1)%Qsize; //尾指针后移,在新位置插入元素
data[rear]=x;
}
int CirQueue::chu(){
//队首出队
if(front==rear) throw"队空!";
front=(front+1)%Qsize; //front最初指向队头元素前一位置。头指针后移,使得原来的的队首元素出队
return data[front];
}
int CirQueue::empty(){
//队空条件:前、后指针相等
if(front==rear) return 1;
else return 0;
}
int CirQueue::get(){
if(front==rear) throw"队空!";
return data[(front+1)%Qsize]; //取队首元素
}
void CirQueue::print(){
cout<<"当前队列中的所有元素为:";
for(int i=front+1;i<=rear;i++) cout<<data[i]<<" ";
cout<<endl;
}
int main(){
int x;
CirQueue C;
if(C.empty()) cout<<"队列空!"<<endl;
cout<<"入队操作!\n";
C.add(5);
C.add(8);
C.print();
cout<<"当前队列队首元素为:"<<C.get()<<endl;
cout<<"-----------------"<<endl;
//尝试让元素出队
cout<<"元素出队!\n";
int t=C.chu();
cout<<"出队的是:"<<t<<endl;
//验证出队效果
cout<<"当前队列队首元素为:"<<C.get()<<endl;
C.print();
return 0;
}
链队列
1.front永远指向队头元素前一位置,front之后才是第一结点
2.判断条件与循环对相同
队空:前、后指针相等.即:front==rear
类的声明
class LinkQueue
{
public:
LinkQueue( ); //构造函数,初始化空链队列
~LinkQueue( ); //析构函数,释放链队列各结点的存储空间
void EnQueue(int x); //入队操作
DataType DeQueue( ); //队首元素出队
DataType GetQueue( ); //取链队列的队头元素
int Empty( ); //判空
private:
Node *front, *rear;
//队头和队尾指针,分别指向头结点和队尾结点
};
功能实现
构造
队头指针和队尾指针都均指向头结点s
int :: LinkQueue( )
{
Node *s = nullptr;
s = new Node; s->next = nullptr; //创建头结点s
front = rear = s; //队头指针和队尾指针都指向头结点s
}
入队
链表实现存储,无需判断队满
void LinkQueue :: EnQueue(int x)
{
Node *s = nullptr;
s = new Node; //辅助结点s
s->data = x; s->next = nullptr;
rear->next = s; rear = s; //将结点s插入队尾
}
出队
需要判断队空: rear == front
int LinkQueue :: DeQueue( )
{
int x;
Node *p = nullptr;
if (rear == front) throw "队空";
p = front->next; x = p->data; //暂存队头
front->next = p->next; //队头摘链
if (p->next == nullptr) rear = front;
//判断出队的元素是否为队列中最后一个元素
delete p;
return x;
}