C语言-数据结构-队列
if((q->rear+1)%maxqsize==q->front) exit(1);q->base[q->rear]=b;q->rear=(q->rear+1)%maxqsize;}
void delete_(sq_queue *q){
if(q->front==q->rear) exit(1);
q->front=(q->front+1)%maxqsize;}
queue gethead(sq_queue *q){
return q->base[q->front];}
每一句都是啥意思啊??? 展开
//插入一个元素b到队列
void insert(sq_queue *q,queue b)
{
//如果队列已满则退出
if((q->rear+1)%maxqsize==q->front)
exit(1);
//未满则将b插入到对尾,同时将对尾赋值为下一个空元素位置
q->base[q->rear]=b;q->rear=(q->rear+1)%maxqsize;
}
//删除队列的对头元素
void delete_(sq_queue *q)
{
//如果队列为空则退出
if(q->front==q->rear)
exit(1);
//非空则删除对头元素,然后移动对头到下一个元素,作为新的对头
q->front=(q->front+1)%maxqsize;
}
//返回对头元素(不删除对头)
queue gethead(sq_queue *q)
{
return q->base[q->front];
}
首先你得明白队列的基本实现。
1. 这是个循环队列,大小是200,也就是只有这么一块200的空间。
2. 队列可以队尾进入,队首离开,这是通过改变队首和队尾的位置实现的。队首和队尾就是包含有效数字的区间。一开始队首和队尾都是0;如果进入一个数字,队尾+1,把放在队尾的新数字包含进去;如果离开一个数字,队首+1,不再包含这个数字。这个和普通的数组不一样,如果用普通的数组,拿掉首元素,你得把所有元素往前移一格,很耗时间。
3. 那么我假如进了200个数字,然后出了199个数字,这时候虽然队里只有1个数字,但是你可以看到队首加了199次,队尾加了两百次,相当于队列像蠕虫一样往前蠕动了一大截。如果我再进200个再出199个,队列又会往前蠕动...很快就会超出内存限制。所以就有了循环队列,比如这里的大小是200的循环队列,假如队首到了201,把它%200,变成1,就像在1和200之间放了个传送门,蠕虫爬到200之后立刻被传送到1,不让他一直往前蠕动。
4. 当然,你这个空间一共就200个,如果数字大于200个肯定就装不下,就报错退出了,这时候就是第一句exit(1)的意思。实际上就是虫子越来越长,一直在循环蠕动,最后就跟贪吃蛇一样撞到自己的尾巴,再也没地方生长了。
下面附上代码和注释:
再重申一次,循环队列相当于传送门,如果队首到达201,就会变成1;比如队首再+300,变成301,它相当于又被传送一次,变成101。这实际上不用写什么“如果队首>200,队首=队首-200)这种,太麻烦,直接用除余(%)的过程就能表示了。所以你看到很多(q->rear+1)%maxqsize这种,实际上就是你每个用到队首+1,队尾+1的地方,都%一下maxqsize就行了,而不用判断”它这个+1是不是超过200了呀?“。理解代码的时候,你也能看到所有+1都跟着%maxqsize,把所有的加一后面的%都去掉就明白了。
请点击输入图片描述
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define maxqsize 200
typedef int queue;
typedef struct{
queue *base;
int front, rear;
}sq_queue;
//你应该少了个初始化,base=new queue[maxqsize];
void insert(sq_queue *q,queue b) //注释从下面开始...
{
if((q->rear+1)%maxqsize==q->front) exit(1);//就是 队尾+1=队首, 像贪吃蛇一样首尾相撞,说明内存200个占满了 ,报错退出 。每个+1都要%一下。这里也要%一下。
q->base[q->rear]=b;//把东西放在队尾
q->rear=(q->rear+1)%maxqsize;//队尾+1,每个+1都要%一下。这里也要%一下。
}
void delete_(sq_queue *q)
{
if(q->front==q->rear) exit(1);//如果队首=队尾,就是队列是空的,报错退出
q->front=(q->front+1)%maxqsize; //队首+1,每个+1都要%一下。这里也要%一下。
}
queue gethead(sq_queue *q)
{
return q->base[q->front];//返回队首的字符
}
在这个队列结构里,queue*base是队列的连续地址,front:队列头的下标,rear:队列尾的下一个地址下标。队列最大长度是maxqsize。
队列是先进先出,比如base是个下标0~9的连续地址(数组)。那么第一个进队列的就在0下标的地址上,第二个进队列的就在1下标地址上,依次排到队伍满(如果期间没有出队的),等0下标的数据出队了,1下标就变成队列的前,而0下标变成队列的后等待新数据插入。
所以在队列进队出队的过程中,下标其实是循环的,所以下面函数才用(q->rear+1)%maxqsize来表示队列下一个要放数据的地址下标。
insert函数从命名就看出是向队列插入数据,也就是入队。这里判断(q->rear+1)%maxqsize==q->front就是判断队列是否已满。如果未满就存放数据,并记录队尾下标。
delete删除数据,也就是就是出队。同理当队列不为空的时候将队头指向下一下标(之前那个队头数据会被新数据覆盖,等同于删除)。
gethead就是获取当前对列头部数据。