您的位置:首页 > 理论基础 > 数据结构算法

数据结构之队列的实现

2016-02-16 15:21 531 查看
数据结构之队列的实现

队列是一种先进先出(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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: