数据结构——循环队列(声明、初始化、判断队空/队满、入队、出队、遍历队)

以下是数据结构中关于循环的声明、初始化、判断空与满、出队、入队、遍历队等基础操作(编程风格参考严蔚敏数据结构)。
本代码主要将书本代码进行补充完成调试的(元素最大数量为MAXSIZE-1),以及自己新加进去的遍历操作。

头文件及宏

#include<iostream>
#include<stdio.h>
using namespace std;
#define QElemType char
#define Status int//表示状态 
#define OK 1
#define ERROR 0
#define MAXSIZE 5

定义声明及初始化

typedef struct SeQueue{
	QElemType *base;
	int front;
	int rear;
}Squeue;

Status initial(Squeue &sq){
	sq.base = new QElemType[MAXSIZE];
	if(!sq.base){
		cout<<"初始化失败\n";
		return ERROR;
	}
	sq.front = sq.rear = 0;
	return OK;
}

步骤:

  1. 声明顺序队列sq;
  2. 给sq的base数组分配内存空间;
  3. 最初没有元素在数组内,队头队尾均设为0。

入队

Status Enqueue(Squeue &sq,QElemType e){
	sq.base[sq.rear] = e;
	sq.rear = (sq.rear+1)%MAXSIZE;//为了让rear一直在[0,MAXSIZXE-1]这个范围 
	return OK;
}

void addElem(Squeue &sq){
	QElemType elem = '0';
	while(elem!='*' && isNotFull(sq)){
		cout<<"请输入元素(输入*结束进队):";
		cin>>elem;
		if(elem!='*'){
			Enqueue(sq,elem);
		}
	}
	cout<<"入队完毕\n";
	showSqueue(sq);
}

步骤:

  1. 先判断是否为满队;
  2. 尾位置新增元素;
  3. 尾位置自增1。

关于sq.rear = (sq.rear+1)%MAXSIZE的解释:
假设MAXSIZE为5,rear的变化只能是在[0,4]这个区间,因为当rear到4的时候,再增加一个元素, (rear+1)%MAXSIZE = 0,就回到0了。

出队

Status Dequeue(Squeue &sq,QElemType &e){
	e = sq.base[sq.front];
	sq.front = (sq.front+1)%MAXSIZE;//为了让front一直在[0,MAXSIZXE-1]这个范围 
	return OK;
}

void delElem(Squeue &sq){
	QElemType elem;
	if(isNotEmpty(sq)){
		if(Dequeue(sq,elem))
			cout<<"出队成功,本次出栈元素为:"<<elem<<endl; 
	}
} 

关于sq.front = (sq.front+1)%MAXSIZE的解释:
假设MAXSIZE为5,front的变化只能是在[0,4]这个区间,因为当front到4的时候,再增加一个元素, (front+1)%MAXSIZE = 0,就回到0了。
循环队列的关键就在这里:front和rear的循环计算方式的思想是一致的,在判断空与满的时候就要使用循环的思想进行判断(因为会出现尾指针的数字小于头指针的情况)。

判断队空/队满

Status isNotFull(Squeue sq){
	cout<<sq.rear<<" "<<sq.front<<endl; 
	if((sq.rear+1)%MAXSIZE == sq.front){ 
		cout<<"队满!\n";
		return ERROR;
	}
	return OK;
}

Status isNotEmpty(Squeue sq){
	if(sq.front==sq.rear){
		cout<<"队空!\n";
		return ERROR;
	}
	return OK;
}

关于满队(sq.rear+1)%MAXSIZE == sq.front的解释:

假设尺寸为5,当front是0时则rear到4的时候就是满队,计算的时候就是(4+1)%5 = 0 = front。

当出队了2个元素后再进队2个元素此时的头位置和尾位置是这样的:
front=2,rear = 1。此时尾指针的数字小于头指针的数据,单纯使用rear-front的思想是行不通的,必须使用循环思想进行思考。

如果说front和rear的最大范围就是MAXSIZE-1,再往下走就是回到循环起点继续递增,周而复始。虽然rear比front小,但是这意味着rear已经走到下一个以MAXSIZE为基数的循环了。对MAXSIZE取余就是去除多出的循环的过程。

(sq.rear+1)%MAXSIZE = (1+1)%5 = 2 = front;此时就是队满。
此时头到尾的下标为:2 3 4 0 1。

但是这种写法的队满数量其实是:MAXSIZE-1(书本也说明了)。
原因如下:
靠(sq.rear+1)%MAXSIZE == sq.front判断队满的话,会导致循环队列里最大元素数量为MAXSIZE-1。
我们来回顾一下入队时的步骤:
入队步骤:

  1. 先判断是否为满队;
  2. 尾位置新增元素;
  3. 尾位置自增1。
    我们入队是元素先入队,尾位置再自增。当尾位置在0的时候,元素入队了,此时尾位置在1的位置,此时1的位置是没有元素的。但是我们判断满队的时候,使用的是“(尾位置+1)%最大尺寸==头位置”的方式进行判断,这就会导致如下结果:
    设最大尺寸MAXSIZE为5:
    当尾位置在3的时候,(3+1)%4 !=0;将新元素填入3的位置,尾位置+1,rear变成4。
    (4+1)%4 ==0,直接就判断为满队跳出了,而此时的4的位置其实还是空的。这种写法就导致队列的元素数量最多只能是MAXSIZE-1。

遍历

void showSqueue(Squeue sq){
	cout<<"当前队元素:\n";
	if(isNotEmpty(sq)){
		int i = sq.front;
		cout<<sq.base[i]<<" ";
		i=(i+1)%MAXSIZE;
		while(i!=sq.rear){
			cout<<sq.base[i]<<" ";
			i=(i+1)%MAXSIZE;
		}
		cout<<endl;
	}
}

运行截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
很高兴可以为你解答这个问题!关于使用C语言建立循环队列,可以按照以下步骤实现: 1.定义列结构体,其中包括列数组、头、尾和列大小等成员变量。 2.初始化列,即将头和尾指针都指向0,表示列为空。 3.实现入队操作,即在尾插入元素,并将尾指针加1。 4.实现出队操作,即将头元素删除,并将头指针加1。 5.实现遍历列操作,可以通过循环遍历列中所有元素,并打印出来。 以下是一个C语言实现循环队列的示例代码: #include <stdio.h> #include <stdlib.h> // 定义列结构体 typedef struct { int* data; // 列数组 int front; // 头指针 int rear; // 尾指针 int maxSize; // 列大小 } Queue; // 初始化列 void initQueue(Queue* q, int maxSize) { q->data = (int*)malloc(maxSize * sizeof(int)); q->front = q->rear = 0; q->maxSize = maxSize; } // 入队操作 void enqueue(Queue* q, int val) { if ((q->rear + 1) % q->maxSize == q->front) { printf("Queue is full\n"); return; } q->data[q->rear] = val; q->rear = (q->rear + 1) % q->maxSize; } // 出队操作 void dequeue(Queue* q) { if (q->front == q->rear) { printf("Queue is empty\n"); return; } q->front = (q->front + 1) % q->maxSize; } // 遍历列操作 void traverse(Queue* q) { int i; printf("Queue elements: "); for (i = q->front; i != q->rear; i = (i + 1) % q->maxSize) { printf("%d ", q->data[i]); } printf("\n"); } // 主函数 int main() { Queue q; int maxSize = 10; initQueue(&q, maxSize); enqueue(&q, 1); enqueue(&q, 2); enqueue(&q, 3); traverse(&q); dequeue(&q); traverse(&q); return 0; } 希望以上代码可以帮助你理解如何使用C语言建立循环队列,如果有其他问题可以继续向我提问哦。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芣苢的成长之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值