循环队列

队列终于要上场了,等很久喽,那就闲言少叙,言归正传,何为队列?请看下图:


这里写图片描述


那何谓循环队列呢?这个,所谓一图胜千言,还是看图吧:


这里写图片描述


原来循环顺序表(线性表的顺序存储方式)的队列形式啊,懂了,兼具循环顺序表和队列两重特性,在实际中还是挺有用的,然后还是老规矩在代码和注释中看看循环队列的各种操作,接下来就是程序员与程序员之间的对话了:

#include <stdio.h>
#include <stdlib.h>
//定义函数结果状态码
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

//定义循环队列空间大小
#define QUEUESIZE 20

//定义数据类型
typedef int ElemType ;
//定义程序返回状态类型
typedef int Status;

//循环队列存储结构
typedef struct _CircleQueue
{
    ElemType data[QUEUESIZE];                  //存储队列元素空间
    int front;                                 //队列头指针
    int rear;                                 //队列尾指针
    int count;                                //队列元素个数
}CircleQueue;


/*************************************************
Function:       InitQueue
Description:    初始化,构造空队列
Input:          队列指针 CircleQueue *queue
Output:
Return:         成功返回OK
Others:         空队列 queue->front = queue->rear = 0
*************************************************/
Status InitQueue(CircleQueue *queue)
{
    queue.data = (ElemType *)malloc(QUEUESIZE * sizeof(ElemType));  
    queue->front = queue->rear = 0;              
    queue->count = 0;
    return OK;

}

//判断循环队列为空和满,一般来说有以下三种方法:
//1、使用计数器count,队列为空和满时,front都等于rear,本程序中采用的是这种方法。
//2、少用一个元素的空间,约定队列满时:(rear+1)%QUEUESIZE=front,为空时front=rear
//   rear指向队尾元素的下一个位置,始终为空;队列的长度为(rear-front+QUEUESIZE)%QUEUESIZE。
//   强调一下,这种方法会保留一个元素空间。
//3、设置一个标志变量flag,当front == rear,且flag = 0 时为队列空,当front == rear,
//   且flag= 1时为队列满。

/*************************************************
Function:       IsQueueEmpty
Description:    队列是否为空
Input:          队列指针 CircleQueue *queue
Output:
Return:         为空返回TRUE,否则返回FALSE
Others:
*************************************************/
Status IsQueueEmpty(CircleQueue *queue)
{
    if(queue->count == 0)
        return TRUE;
    else
        return FALSE;
}

/*************************************************
Function:       IsQueueFull
Description:    队列是否为满
Input:          队列指针 CircleQueue *queue
Output:
Return:         为满返回TRUE,否则返回FALSE
Others:
*************************************************/
Status IsQueueFull(CircleQueue *queue)
{
    if(queue->count == QUEUESIZE)
        return TRUE;
    else
        return FALSE;
}

/*************************************************
Function:       EnQueue
Description:    入队
Input:          队列指针 CircleQueue *queue
                数据元素   ElemType e
Output:
Return:         成功返回OK,失败返回ERROR
Others:
*************************************************/
Status EnQueue(CircleQueue *queue, ElemType e)
{
    //验证队列是否已满
    if(queue->count == QUEUESIZE)
    {
        printf("The queue is full");
        return ERROR;
    }
    //入队
    queue->data[queue->rear] = e;
    //队尾指针后移
    queue->rear = (queue->rear + 1) % QUEUESIZE;
    //更新队列长度
    queue->count++;
    return OK;

}

/*************************************************
Function:       DeQueue
Description:    出队
Input:          队列指针 CircleQueue *queue
Output:
Return:         成功返回数据元素,失败程序退出
Others:
*************************************************/
ElemType DeQueue(CircleQueue *queue)
{
    //判断队列是否为空
    if(queue->count == 0)
    {
        printf("The queue is empty!");
        exit(EXIT_FAILURE);
    }

    //保存返回值
    ElemType e = queue->data[queue->front];
    //更新队头指针
    queue->front = (queue->front + 1) % QUEUESIZE;
    //更新队列长度
    queue->count--;

    return e;
}

/*************************************************
Function:       GetHead
Description:    取队头元素
Input:          队列指针 CircleQueue *queue
Output:
Return:         成功返回数据元素,否则程序退出
Others:
*************************************************/
ElemType GetHead(CircleQueue *queue)
{
    //判断队列是否为空
    if(queue->count == 0)
    {
        printf("The queue is empty!");
        exit(EXIT_FAILURE);
    }

    return queue->data[queue->front];
}

/*************************************************
Function:       TraverseQueue
Description:    遍历整个队列
Input:          队列指针 CircleQueue *queue
Output:
Return:         无
*************************************************/
void TraverseQueue(CircleQueue *queue)
{
    int i = queue.front;                     //首先获取队列头指针
    while(i != queue.rear)                   //以是否到尾指针来进行判断
    {  
        printf("%d ",queue.data[i]); 
        i = (i+1) % QUEUESIZE;              //这一步很重要,自己体会,嘿嘿!
    }  
    printf("\n");                     
}

/*************************************************
Function:       ClearQueue
Description:    清空队列
Input:          队列指针 CircleQueue *queue
Output:
Return:         成功返回OK
Others:
*************************************************/
Status ClearQueue(CircleQueue *queue )
{
    queue->front = queue->rear = 0;
    queue->count = 0;
    return OK;
}

/*************************************************
Function:       GetLength
Description:    取得队列的长度
Input:          队列指针 CircleQueue *queue
Output:
Return:         返回队列的长度
Others:
*************************************************/
int GetLength(CircleQueue *queue)
{
    return queue->count;
}
/*************************************************
Function:       DestroyQueue
Description:    销毁队列
Input:          队列指针 CircleQueue *queue
Output:
Return:         成功返回OK
Others:
*************************************************/
Status DestroyQueue(CircleQueue *queue )
{
    ClearQueue( queue );                //首先清空队列
    if(queue.data)
    {
       free(queue.data);              //然后销毁存储队列元素的数组空间
       queue.data = NULL;             //因为数组在内存里本质上就是指针,所以这一步是防止野指针的出现
    }
    free(queue);                      //最后销毁循环队列结构体
    return OK;
}

和栈一样,队列的时间复杂度也是O(1);空间的话就是一个固定的数组长度了,一谈到固定,弊端就出来了,很多时候无法固定的,所以固定了很容易溢出,怎么办,这时候可以考虑链队列,链队列就下期见喽!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值