循环队列

Posted 四季帆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环队列相关的知识,希望对你有一定的参考价值。

1. 循环队列的概念

在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置,自动从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。

循环队列就是将队列存储空间的最后一个位置转而绕到第一个位置,形成逻辑上的环状空间,但我们需要注意,实际上循环队列不是一个真正的环,它依旧是单线性的。

使用循环队列虽然可以解决顺序队列中浪费内存的问题,但这里任然存在一个问题,就是对于循环队列而言,队空和队满的条件都是rear==front,导致两种情况无法区分。 为了区分队空和队满,可以采用空一个元素不使用的方法,此时队空的条件为:front==rear,而队满的条件则为:(rear+1)%MAXSIZE == front,从而加以区分。

 

2. 代码实现

在数组实现的顺序链表基础上进行改进

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

typedef struct Qnode
{
    int *Data;
    int Front,Rear;
    int Max;
} *Queue;

//创建一个空队列
Queue CreateQueue(int max)
{
    Queue q = (Queue)malloc(sizeof(struct Qnode));
	q->Data = (int *)malloc(sizeof(int) * max);
	q->Front = q->Rear=0;
    q->Max = max;
    return q;
}

//入队
void AddQueue(Queue q, int data)
{
	if ((q->Rear+1)%q->Max == q->Front)
    {
        printf("ERROR: Queue is full!\\n");
    }
    else
    {
        //只能填充MAX-1个数据,永远有一个格子没有数据
        q->Rear = (q->Rear+1)%q->Max;
        q->Data[q->Rear] = data;
        printf("add queue data = %d\\n", data);
    }
}
//出队
void OutQueue(Queue q, int *data)
{
    if(q->Front == q->Rear)
    {
        printf("ERROR: Queue is empty\\n");
    }
    else
	{
         q->Front = (q->Front+1)%q->Max;
        *data = q->Data[q->Front];
    }
}
int main()
{
    int i, temp;
    Queue q;
    
    q=CreateQueue(10);       //创建一个队长为10的空队列    
    //for(i=0;i<10;i++)      //入队10个数字是不可以的,入队第10个数字时会报错队列已满
	for(i=0;i<9;i++)        //一次最多只能入队9个数字,因为环形队列有一个格子是要空着的
        AddQueue(q,i);
    for(i=0;i<5;i++)	//出队5个数字并打印
    {
        OutQueue(q, &temp);
        printf("%d\\n", temp);
    }
    return 0;
}

3. 总结

数组实现的顺序链表因为空间不能重复使用,实际工作中基本没啥用处,直接PASS;

链表实现的顺序链表空间是可以重复使用的,但是每次入队和出队动作都需要动态申请内存,这对于频繁进行入队和出队的程序来说,是非常影响其效率的;

循环链表是在数组实现的顺序链表上做了些许改进而得到的,它的空间可以重复使用,入队和出队也不需要动态申请内存,所以这种方式在实际工作当中使用得最广泛。

 

以上是关于循环队列的主要内容,如果未能解决你的问题,请参考以下文章

常用python日期日志获取内容循环的代码片段

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

AVKit – 视频片段仅循环 2 次

如何使用事件侦听器来加载动画片段的循环

用java实现循环队列?

java-----循环队列