队列
(1) 队列的定义
队列(queue)是由有限个数据类型相同元素所组成的有序集合,
对元素的操作只能在队列的队头和队尾进行,
遵循先进先出(First In,First Out)的原则,
其相关运算函数有创建空队,判空,判满,入队,出队等
(2) 队列的ADT
ADT Queue
数据:
有限个数据类型相同元素所组成的有序集合,用front,rear记录队头,队尾元素位置.
运算:
Create() 创建空队
IsEmpty() 判空:若队空,则返回 1,否则 返回 0;
IsFull() 判满:若队满,则返回 1,否则 返回 0;
InQueue() 让某元素从队尾入队
OutQueue() 让队头元素出队
Display() 输出队列元素
(3) 队列的数组实现
定义数组data[MaxSize]用来存储队列元素,
MaxSize是允许的最大容量,
用变量front,rear记录队头,队尾元素位置,front=rear=-1表示空栈,
这种队列称为顺序队列(Sequence queue).
#include<iostream>
using namespace std;
#define MaxSize 4
//顺序队列定义
struct SeqQueue{
int data[MaxSize];
int front,rear;
};
//创建空队
void Create(SeqQueue &Q){
Q.front=Q.rear=-1;
}
//判空:若队空,则返回 1,否则 返回 0;
int IsEmpty(SeqQueue Q){
if(Q.front == -1&&Q.rear == -1) return 1;
else return 0;
}
//判满:若队满,则返回 1,否则 返回 0;
int IsFull(SeqQueue Q){
if(Q.rear >= MaxSize-1) return 1;
else return 0;
}
//让某元素从队尾入队
void InQueue(SeqQueue &Q,int x){
if(IsFull(Q)){
cout<<"队列已满,无法入队"<<endl;
return;
}
if(IsEmpty(Q)){
Q.data[0]=x;
Q.front=Q.rear=0;
}else{
Q.data[++Q.rear]=x;
}
}
//让队头元素出队
void OutQueue(SeqQueue &Q,int &x){
if(IsEmpty(Q)){
cout<<"队列为空,无法出队"<<endl;
return;
}
if(Q.rear == Q.front){
x=Q.data[Q.front];
Q.front=Q.rear=-1;
}else{
x=Q.data[Q.front];
for(int i=0;i<Q.rear;i++)
Q.data[i]=Q.data[i+1];
Q.rear--;
}
}
//输出队列元素
void Display(SeqQueue Q){
if(IsEmpty(Q)){
cout<<"队列为空,无内容输出"<<endl;
return;
}
int i=Q.front;
while(i<=Q.rear)
cout<<Q.data[i++]<<" ";
cout<<endl;
}
int main(){
SeqQueue Q;
Create(Q);
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
InQueue(Q,5);
cout<<"队列情况:";Display(Q);
int x;
for(int i=0;i<4;i++){
OutQueue(Q,x);
cout<<"出队元素:"<<x<<endl;
cout<<"队列情况:";Display(Q);
}
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
InQueue(Q,5);
cout<<"队列情况:";Display(Q);
}
用移动队列元素的方法,可以避免"假溢出"问题,但当队里元素过多时,移动会消耗许多时间.
(4) 队列的链表实现
由于单链表的长度是动态的,
所以,用单链表实现的队列,不需要判满运算.
用front=rear=NULL表示空队列,
这种队列称为链队(link queue).
由于链队需遵循先进先出的原则,链队创建应采用后插法来实现.
#include<iostream>
using namespace std;
//结点定义
struct Node{
int data;
Node *next;
};
//链队定义
struct LinkQueue{
Node *front,*rear;
};
//创建空链队
void Create(LinkQueue &Q){
Q.front=Q.rear=NULL;
}
//判空
int IsEmpty(LinkQueue Q){
if(Q.front==NULL&&Q.rear==NULL) return 1;
else return 0;
}
//入队
void InQueue(LinkQueue &Q,int x){
Node *NewNode;
NewNode=new Node;
NewNode->data=x;
NewNode->next=NULL;
if(IsEmpty(Q)){
Q.front=Q.rear=NewNode;
}else{
Q.rear->next=NewNode;
Q.rear=NewNode;
}
}
//出队
void OutQueue(LinkQueue &Q,int &x){
if(IsEmpty(Q)){
cout<<"链队为空,无元素出队"<<endl;
return;
}
Node *p=Q.front;
x=p->data;
if(Q.front == Q.rear){
Q.front=Q.rear=NULL;
delete p;
}else{
Q.front=Q.front->next;
delete p;
}
}
//输出链队
void Display(LinkQueue Q){
if(IsEmpty(Q)){
cout<<"链队为空,无内容输出"<<endl;
return;
}
Node *p=Q.front;
while(p!=NULL){
cout<<p->data<<"=>";
p=p->next;
}
cout<<"NULL
"<<endl;
}
int main(){
LinkQueue Q;
Create(Q);
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
cout<<"链队情况:";Display(Q);
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
cout<<"链队情况:";Display(Q);
int x;
for(int i=0;i<6;i++){
OutQueue(Q,x);
cout<<"出队元素:"<<x<<endl;
cout<<"链队情况:";Display(Q);
}
}
(5) 循环队列
循环队列是一种环状队列,用数组data[MaxSize]存储队列元素,
但规定:data[MaxSize-1]的下一个元素为data[0],
rear指向队尾元素,front指向队头元素的前一个位置(并约定该位置的存储空间被弃置),
用front=rear=-1表示空队.
之所以规定front指向队头元素的前一个位置(并约定该位置的存储空间被弃置),
主要是为了方便队满判定,出队入队指针移动,队头元素获取和队列元素个数的计算.
1. 队满条件
(rear+1)%MaxSize == front;
2. 队头元素
data[(front+1)%MaxSize]
3. 队列元素个数
(MaxSize+rear-front)%MaxSize
4. 出队(头指针进1)
(front+1)%MaxSize
5. 入队(尾指针进1)
(rear+1)%MaxSize
#include<iostream>
using namespace std;
#define MaxSize 4
//循环队列定义
struct CircleQueue{
int data[MaxSize];
int front,rear;
};
//创建空队
void Create(CircleQueue &Q){
Q.front=Q.rear=-1;
}
//判空:若队空,则返回 1,否则 返回 0;
int IsEmpty(CircleQueue Q){
if(Q.front == -1&&Q.rear == -1) return 1;
else return 0;
}
//判满:若队满,则返回 1,否则 返回 0;
int IsFull(CircleQueue Q){
if((Q.rear+1)%MaxSize == Q.front) return 1;
else return 0;
}
//让某元素从队尾入队
void InQueue(CircleQueue &Q,int x){
if(IsFull(Q)){
cout<<"队列已满,无法入队"<<endl;
return;
}
if(IsEmpty(Q)){
Q.data[0]=x;
Q.front=MaxSize-1;
Q.rear=0;
}else{
Q.rear=(Q.rear+1)%MaxSize;
Q.data[Q.rear]=x;
}
}
//让队头元素出队
void OutQueue(CircleQueue &Q,int &x){
if(IsEmpty(Q)){
cout<<"队列为空,无法出队"<<endl;
return;
}
if((Q.front+1)%MaxSize == Q.rear){
Q.front=(Q.front+1)%MaxSize;
x=Q.data[Q.front];
Q.front=Q.rear=-1;
}else{
Q.front=(Q.front+1)%MaxSize;
x=Q.data[Q.front];
}
}
//输出队列元素
void Display(CircleQueue Q){
if(IsEmpty(Q)){
cout<<"队列为空,无内容输出"<<endl;
return;
}
int i=(Q.front+1)%MaxSize;
int n=(MaxSize+Q.rear-Q.front)%MaxSize;
for(int j=1;j<=n;j++){
cout<<Q.data[i]<<" ";
i=(i+1)%MaxSize;
}
cout<<endl;
}
int main(){
CircleQueue Q;
Create(Q);
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
InQueue(Q,5);
cout<<"队列情况:";Display(Q);
int x;
for(int i=0;i<4;i++){
OutQueue(Q,x);
cout<<"出队元素:"<<x<<endl;
cout<<"队列情况:";Display(Q);
}
InQueue(Q,1);
InQueue(Q,2);
InQueue(Q,3);
InQueue(Q,4);
InQueue(Q,5);
cout<<"队列情况:";Display(Q);
}
(6) 优先队列
优先队列(priority queue)是一种不必遵循先进先出原则的队列,
队列元素都被赋予了一个优先级,优先级高的元素可先入队,先出队.
写于2020-10-23