队列定义和操作与循环队列

队列

1.队列定义

1.1 结构定义

说明:首先考虑普通队列的实现,不考虑队列假溢出的情况

  1. 首先要有一块连续的存储空间,存储的数量,以及指向队列头部和尾部的指针元素
  2. 在此处head和tail同样也只是数组的索引值,然后通过数组就可以取值
typedef struct Queue{
	int *data; //一块连续的存储空间
	int size;
	int head,tail; 
}Queue; 
1.2 初始化

在这里插入图片描述

  1. 初始化,开辟内存空间,只需传入队列变量的引用,和队列的最大数量即可
  2. 声明变量后数据要在堆区开辟空间才行
void init_queue(Queue &q,int n){
	q.data = new int[n];
	q.size = n;
	//头和尾均指向空
	q.head = 0;
	q.tail = 0;
} 
1.3 判空操作
bool empty(Queue q){
	return q.head == q.tail; 
} 
1.4 结构操作

结构操作,推入(将值放入到队列中)和弹出,队列是先进先出,而且不能指定位置

在这里插入图片描述

1.4.1 推入

​ 进入时改变的一直都是尾部索引,头部不变 进入时改变的一直都是尾部索引,头部不变

void push(Queue &q,int val){
	//1.首先判断是否满了
	if(q.size == q.tail) return;
	//2.接着进行推入
	q.data[q.tail++] = val;//因为初始时tail指向的是0,所以先对data[0]赋值之后再加一 
	return ; 
} 
1.4.2 弹出

​ 尾部出去,尾部放的是head指向的,所以改变的是头部

void pop(Queue &q){
	//1.首先判断队列是否是空的 
	if(empty(q)) return;
	//2.头部指针向后移动
	q.head++; 	
} 
1.5 展示

​ 从head开始到tail进行循环

void display(Queue q){
	cout<<"queue["<<q.size<<"]= [";
	for(int i=q.head;i<q.tail;i++){
		cout<<q.data[i]<<" ";
	}
	cout<<"]"<<endl;
}
1.6 整理执行
#define MAX_OP 30  //定义最大的队列长度
int main(){
	Queue q1;// 当传入的是引用时就不能使用指针了 
	init_queue(q1,MAX_OP);
	for(int i=0;i<MAX_OP;i++){
		int val = rand()%100;
		int op = rand()%4;
		switch(op){
			case 0:{
				cout<<"push "<<val<<" into queue"<<endl;
				push(q1,val);
				break;
			}			
			case 1:{
				cout<<"push "<<val<<" into queue"<<endl;
				push(q1,val);
				break;
			}			
			case 2:{
				cout<<"push "<<val<<" into queue"<<endl;
				push(q1,val);
				break;
			}
			case 3:{
				cout<<"pop "<<q1.data[q1.head]<<" from queue"<<endl;
				pop(q1);
				break;
			}
		}
		display(q1);
	}

	return 0;
}

*** 执行结果 😗**

​ 循环30次,对可以存放30个元素的队列中进行随机的推入和弹出操作,所以不需要考虑出现假溢出的情况
在这里插入图片描述

2.循环队列

​ 只是将上面的队列进行了简单修改,注释即修改后的地方

以下是考虑假溢出的循环队列
循环队列是为了解决
假如一个空队列只能有5个元素,而此时队列中已经存有5个元素,此时head == 0,tail == 5,下一时刻弹出一个元素,即head == 1,tail == 5,
若此时再推入一个元素,如果仍然如同上面所写的那样 的判断条件 if(q.size == q.tail) return;就直接返回了是不对的
,但显然此时队列还没有存满,循环队列就是为了解决这个问题

//1.结构定义
typedef struct Queue{
	int *data; 
	int cnt;//循环队列需要加上一个计数的变量 ,用于表示当前队列中的数量 
	int size;
	int head,tail; 
}Queue; 

//2.初始化

void init_queue(Queue &q,int n){
	q.data = new int[n];
	q.size = n;
	q.head = 0;
	q.tail = 0;
	q.cnt = 0; //需要初始化为0 
} 

//3. 清除队列
void clear(Queue &q){
	delete q.data;
} 

//4.结构操作
//4.1 推入
void push(Queue &q,int val){
	//1.插入时就不能仅仅通过判断尾部表示已满,而是要判断实际所存的数才对
//	if(q.size == q.tail) return;
	if(q.cnt == q.size) {
		cout<<"队列已满,不可再推入"<<endl; 
		return;
	}
	//2.接着进行推入
	q.data[q.tail++] = val;
	//3.并且当尾部指向末尾时要重新指向队列的实际头部
	if (q.tail == q.size) {
		q.tail -= q.size;//即此时tail == 0
	}
	//4.且计数要加1
	q.cnt += 1;
	return ; 
} 
//4.2 判空 
bool empty(Queue q){
	//显然当计数为0时队列为空,
	//因为head,tail循环所以很有可能当head == tail时并不为0 
//	return q.head == q.tail; 
	return q.cnt == 0;
} 

//4.3 弹出,
void pop(Queue &q){

	if(empty(q)) return;

	q.head++; 
	//1.弹出则时当头指针指向末尾后重新返回真正的头
	if (q.head == q.size) {
		q.head -= q.size;
	}
	//2.同时计数要减一
	q.cnt -= 1;
	
} 

//5.展示
void display(Queue q){
	cout<<"queue["<<q.cnt<<"]= [";
	//同样输出也是要从头部输出,要循环计数次
	for(int i=q.head,j = 0;j< q.cnt;j++){
	//	cout<<q.data[i]<<" ";
	   int ind = (i + j) % q.size; 
    	cout<<q.data[ind]<<" ";
	}
	cout<<"]"<<endl;
	cout<<endl;
} 

*** 结果显示: ***

​ 循环30次,向只能存放10个元素的队列中推入或弹出数据的结果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值