队列

队列

(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值