一、概念:
队列是一种特殊的线性表,尽在两端进行操作,队头:取出数据元素的一端;队尾:插入数据元素的一端,队列是不允许在中间部位进行操作的,所以队列是先进先出,(first in first out FIFO ) 允许插入的一端是队尾,允许删除的一端是队头。如图所示:
上面就是队列的逻辑示意图,所以我们可以通过线性表的链式存储来模仿队列的链式存储。
二、队列的API函数:
1.队列的常用操作:
- 销毁队列
- 清空队列
- 进队列
- 出队列
- 获取队头元素
- 获取队列的长度
2.我们首先需要创建一个队列的业务逻辑结构体:
因为队列是特殊的线性表,所以我们写队列的链式存储的代码时候,我们利用了前面学习的线性表链式存储的代码:
1>queue.h
#ifndef __QUEUE__
#define __QUEUE__
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"seqlist.h"
typedef void queue;
queue * queue_create();
void queue_destroy(queue *q);
void queue_clear(queue *q);
int queue_append(queue *q,void *item);
void *queue_retrieve(queue *q);
void * queue_header(queue *q);
int queue_length(queue *q);
#endif
2>queue.c
#include"queue.h"
typedef struct _queue_node
{
list_node node;
void *item;
}queue_node;
queue * queue_create()
{
int ret = 0;
queue * tmp = NULL;
tmp = seqlist_create();
if (NULL == tmp)
{
ret = -1;
printf("queue_create error :%d \n",ret);
return NULL;
}
return tmp;
}
void queue_destroy(queue *q)
{
seqlist_destroy(q);
return;
}
void queue_clear(queue *q)
{
seqlist_clear(q);
return ;
}
int queue_append(queue *q,void *item)
{
int ret= 0;
queue_node *tmp = NULL;
tmp = (queue_node *)malloc(sizeof(queue_node));
if(NULL == tmp)
{
ret = -1;
printf("queue_append malloc error :%d \n",ret);
return ret;
}
memset(tmp,0,sizeof(queue_node));
tmp->item = item;
ret = seqlist_insert(q,(list_node *)tmp,seqlist_length(q));
if(ret != 0)
{
ret = -2;
printf("queue_append malloc error :%d \n",ret);
return ret;
}
return 0;
}
//出队列,从线性表中删除0号位置元素
void *queue_retrieve(queue *q)
{
int ret = 0;
queue_node *tmp = NULL;
void *tmp1 = NULL;
tmp = (queue_node *)seqlist_delete(q,0);
if(NULL == tmp)
{
ret =-1;
printf("queue_retrieve error :%d \n",ret);
return NULL;
}
tmp1 = tmp->item;
if(tmp != NULL)
{
free(tmp);
}
return tmp1;
}
void* queue_header(queue *q)
{
int ret = 0;
queue_node *tmp = NULL;
void * tmp1 = NULL;
tmp = (queue_node *)seqlist_get(q,0);
if(NULL == tmp)
{
ret = -1;
printf("queue_header error :%d \n",ret);
return NULL;
}
return tmp->item;
}
int queue_length(queue *q)
{
return seqlist_length(q);
}
3>main.c(测试代码)
#include<stdio.h>
#include"queue.h"
int main(int argc,char* argv[])
{
queue *qu = queue_create();
int i = 0;
int arr[10] = {0};
for(i = 0;i < 10;i++)
{
arr[i] = i+10;
}
for(i = 0; i <10;i++)
{
queue_append(qu,&arr[i]);
}
int length = queue_length(qu);
printf("队列的长度为:%D \n",length);
int head = *((int *)queue_header(qu));
printf("队首的位置为:%d \n",*((int *)queue_header(qu)));
printf("一个一个清空队列 \n");
for(i =0;i < 10;i++)
{
printf("插入的顺序元素为:%d",*((int *)queue_retrieve(qu)));
}
printf(" \n");
return 0;
}
总结:
1.
typedef struct _queue_node
{
list_node node;
void *item;
}queue_node;
在队列中,这个队列节点,和栈节点一样,这是用来定义一个中间变量的,因为我们传进来的是一个业务节点,而我们的队列用的是线性表来模仿的,所以,业务节点无法插进去队列,所以这个时候我们需要的是一个中间变量,充当线性表的节点,还可以同时将业务节点数据保存进线性表,所以我们定义了一个这样的中间数据类型;
2.整个代码是线性表来模仿队列,所以更能证明,其实队列就是一种特殊的线性表。