数据结构之队列的实现

数据结构之队列的实现

队列是一种先进先出(First-IN First-OUT, FIFO)的结构,实现队列一般有两种方法,第一是使用链表的形式实现,另外一种是使用数组实现。下面分别以这两种方式实现数据结构中的队列。

一、 使用链表实现
队列一般就有下列几个函数:
void init_queue(queue_node *queue); //初始化队列
bool in_queue(queue_node *queue,queue_type value);//进队
bool queue_is_empty(queue_node *queue);//判断队列是否空
bool queue_is_full(queue_node *queue);//判断队列是否已满
queue_type out_queue(queue_node *queue);//出队

代码实现如下:

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

#define ITEMS_MAX 125  //队列最大的容量
typedef int  queue_type; //队列数值的类型

/*队列节点*/
typedef struct _node
{
    queue_type value;
    struct _node *next;
}node;

typedef struct _queue_node
{
    node *front;
    node *rear;
    int items;   //记录队列中项目的个数
}queue_node;

int main(void)
{
    unsigned char i;
    queue_type value;
    /*定义一个队列并初始化*/
    queue_node q;
    init_queue(&q);

    /*in_queue*/
    for(i=1; i<125; i++)
    {
        if(queue_is_full(&q))
        {
            printf("queue is full\n");
            exit(-1);   
        }
        else
        {
            in_queue(&q,i); 
        }
    }

    /*out_queue*/
    for(i=1; i<125; i++)
    {
        if(queue_is_empty(&q))
        {
            printf("queue is empty\n");
            exit(-1);
        }
        else
        {
            value = out_queue(&q);
            printf("%d\n",value);   
        }

    }       
}

/*@brief  Initialize a queue
 *@param  queue:pointer to a queue_node structrue 
 *@retval None
*/
void init_queue(queue_node *queue)
{
    queue->front = NULL;
    queue->rear = NULL;
    queue->items = 0;
}


/*@brief  queue up
 *@param  queue_node:Pointer to a queue_node structrue
 *        queue_type:
 *@retval None
*/
bool in_queue(queue_node *queue,queue_type pvalue)
{
    node *pnew;
    pnew = (node*)malloc(sizeof(node));
    if(pnew == NULL)
    {
        printf("create a new queue node false\n");
        return false;   
    }
    pnew->value = pvalue;
    pnew->next = NULL;

    if(queue_is_empty(queue)) //初次
    {
        queue->front = pnew;
        queue->rear = pnew;
    }
    else
    {
        queue->rear->next = pnew; //链接到队尾尾端
        queue->rear = pnew;       //记录队尾尾端位置
    }

    queue->items++;

    return true;
}

/*@brief  whether the queue is empty
 *@param  queue_node:Pointer to a queue_node structrue
 *@retval None
*/
bool queue_is_empty(queue_node *queue)
{   
    if(queue->items == 0)
    {
        return true;
    }   
    else
    {
        return false;
    }
}

/*@brief  whether the queue is full
 *@param  queue_node:Pointer to a queue_node structrue
 *@retval None
*/
bool queue_is_full(queue_node *queue)
{   
    if(queue->items >= ITEMS_MAX)
    {
        return true;
    }   
    else
    {
        return false;
    }
}



/*@brief  queue out 
 *@param  queue_node:Pointer to a queue_node structrue
 *@retval None
*/
queue_type out_queue(queue_node *queue)
{   
    queue_type temp;
    node *p;

    if(queue_is_empty(queue))
    {
        printf("The queue is empty\n");
        exit(-1);
    }

    temp = queue->front->value;
    p = queue->front;
    queue->front = queue->front->next;
    free(p);

    queue->items--;
    if(queue->items == 0)
    {
        queue->rear = NULL; 
    }

    return temp;    
}

二、使用数组实现队列
使用数组实现队列,当有出队时,如果不把后面的数据向前移动,这样就会造成队列的容量越来越小,如果把后面的数据向前移动,就会造成很大开销;
这里写图片描述

解决这样个问题就是使用循环数组的形式,就是把队列的尾部环绕到数组的头部;这样当已出队删除的位置可以从新存储入队。
这里写图片描述

使用循环数组实现队列,又会引出另外一个问题,就是无法区别队列满与空,
当队列为满时如下所示:
这里写图片描述

当队列为满时,把队列中的元素都出列,那么队列就空了,为空时如下所示:
这里写图片描述

所以循环数组实现队列有无法识别队列满与队列空的现象,解决这一问题可以引入一个变量记录队列的元素,也可以牺牲队列中一个元素位置,来区分满与空,下面代码就是使用牺牲一个元素位置来区分的。

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

//队列容量大小,实质是100-1,一个位置空出用于区分队列满与空
#define QUEUE_DEEP  100 
typedef unsigned char queue_type; //队列数值类型


typedef struct _queue_msg
{    
  queue_type buffer[QUEUE_DEEP];
  unsigned char front;
  unsigned char rear;
}queue_msg;


/*定义并初始化一个队列*/
queue_msg queue=
{
    .front = 1,
    .rear = 0,
};

bool queue_is_empty(queue_msg *queue);
bool queue_is_full(queue_msg *queue);
bool in_queue(queue_msg *queue,queue_type value);
queue_type out_queue(queue_msg *queue);

int main(void)
{
    unsigned char i;
    queue_type value;

    /*in_queue*/
    for(i=1; i<=99; i++)
    {   
        in_queue(&queue,i); 
    }
    /*out_queue*/
    for(i=1; i<=99; i++)
    {
        value = out_queue(&queue);
        printf("%d\n",value);   
    }
    value = out_queue(&queue);      
}

bool in_queue(queue_msg *queue,queue_type value)
{
    if(queue_is_full(queue))
    {
        printf("The queue is fulled\n");
        exit(-1);
    }
    else
    {
        //等价与 queue->rear = (queue->rear+1)%QUEUE_DEEP;
        queue->rear++;
        if(queue->rear >= QUEUE_DEEP)
        {
            queue->rear = 0;
        }
        queue->buffer[queue->rear] = value;
    }
    return true;
}

queue_type out_queue(queue_msg *queue)
{
    queue_type temp;

    if(queue_is_empty(queue))
    {
        printf("The queue is empty\n");
        exit(-1);
    }
    else    
    {
        //等价与 queue->front = (queue->front+1)%QUEUE_DEEP
        temp = queue->buffer[queue->front];
        queue->front++;
        if(queue->front >= QUEUE_DEEP)
        {
            queue->front = 0;
        }
    }
    return temp;
}
//判断队列是否空
bool queue_is_empty(queue_msg *queue)
{
    return ((queue->rear+1)%QUEUE_DEEP == queue->front);
}
//判断队列是否满
bool queue_is_full(queue_msg *queue)
{
    return ((queue->rear+2)%QUEUE_DEEP == queue->front);
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值