数据结构之循环队列

4.10 队列的定义
队列定义:一种先进先出的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。

        队头                           队尾
出队列   a1   a2   a3   a4    .....    an  入队列

队列有类似线性表的各种操作,不同的就是插入数据只能在队尾进行,删除数据只能在队头进行。

线性表有线性存储和链式存储。栈是线性表,有这两种存储方式。
队列作为一种特殊的线性表,也有这两种存储方式。先看队列的线性储存结构。
4.12 循环队列
4.12.1 队列顺序存储的不足

为了避免当只有一个元素时,队头和队尾重合使处理变得麻烦,所以引入两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样当front等于rear时,此队列不是还剩一个元素,而是空队列。(删除)

假溢出:假设这个队列的总个数不超过5个,但目前如果接着入队的话,因数组末尾元素已经占用,再向后加,就会产生数组越界的错误,可实际上,我们的队列在下标为0和1的地方还是空闲的。这种现象“假溢出”。


4.12.2 循环队列的定义
所以假溢出的问题就是后面满了就再从头开始,也就是头尾相接的循环。
把队列的这种头尾相接的顺序存储结构称为循环队列。

(1)此时问题是,我们刚才说,空队列时,front等于rear时,现在当队列满时,也是front等于rear,那么如何判断此时的队列究竟是空还是满?(元素入队)
(2)办法一设置一个标志变量flag,当front == rear,且flag = 0时为队列空,当front == rear,且flag = 1时为队列满。
(3)办法二是当队列空时,条件就是front == rear,当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。

重点讨论第二种方法,由于rear的值可能比front大,也可能比front小,所以尽管他们只相差一个位置时就是满的情况,但也有可能相差整一圈。
所以队列满的条件是  (rear+1)%数组长度 == front 取模的目的就是为了整合rear和front大小为一个问题。

通用的计算队列长度的公式:

(rear - front + 数组长度)% 数组长度

循环队列实现代码如下:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

//宏定义数组长度
#define LENGTH  6

//循环队列的顺序存储结构
typedef struct Qqueue
{
int *pbase;  //指针指向数组
int front;   //头指针
int rear;    //尾指针,若队列不为空,指向队列尾元素的下一个位置
// int length;  数组长度放这里不合适  
} queue, *pqueue;


//函数声明
//初始化空队列
void init_queue(pqueue list);
//队列满判断
bool full_queue(pqueue list);
//入队操作
bool en_queue(pqueue list,int val);
//队列空操作
bool empty_queue(pqueue list);
//出队操作
bool de_queue(pqueue list,int *val);
//遍历输出
void tranverse_queue(pqueue list);
//返回队列元素个数
int num_queue(pqueue list);


int main(void)
{
queue list; //定义一个队列元素

int val = 0;
int num = 0;

init_queue(&list);
en_queue(&list,1);
en_queue(&list,2);
en_queue(&list,3);
en_queue(&list,4);
en_queue(&list,5);
en_queue(&list,6);

tranverse_queue(&list);
num = num_queue(&list);
printf("队列的元素个数num = %d.\n",num);
if(de_queue(&list,&val))
{
printf("出队成功,出队的元素是:%d.\n",val);
}
else
{
printf("出队失败!\n");
}


tranverse_queue(&list);
num = num_queue(&list);
printf("队列的元素个数num = %d.\n",num);
return 0;
}


//初始化一个空队列,数组的长度length放这里也不合适
void init_queue(pqueue list)
{
list->pbase = (int *)malloc(sizeof(int) * LENGTH);
if(NULL == list->pbase)
{
printf("分配内存失败!\n");
exit(-1);
}
else
{
list->front = 0;
list->rear = 0;
}


return ;
}
//队列满的判断
bool full_queue(pqueue list)
{
if( (list->rear+1)% LENGTH == list->front )
{
return true;
}
else
{
return false;
}
}
//入队
bool en_queue(pqueue list,int val)
{
if(full_queue(list))
{
return false;
}
else
{
list->pbase[list->rear] = val;
list->rear = (list->rear + 1) % LENGTH;


return true; 
}
}
//队列遍历输出
void tranverse_queue(pqueue list)
{
int i;
i = list->front;


while(i != list->rear)
{
printf("%d ",list->pbase[i]);
i = (i + 1) % LENGTH;
}


printf("\n");
}
//判断队列为空
bool empty_queue(pqueue list)
{
if(list->front == list->rear)
{
return true;
}
else
{
return false;
}
}
//出队
bool de_queue(pqueue list,int *val)
{
if(empty_queue(list))
{
return false;
}
else
{
*val = list->pbase[list->front];
list->front = (list->front + 1) % LENGTH;


return true;
}
}
//返回队列元素个数
int num_queue(pqueue list)
{
int num;
num = (list->rear - list->front + LENGTH) % LENGTH;

return num;
}


出自:大话数据结构、严蔚敏老师之 数据结构
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值