一、队列
1.定义
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。
2.特点
- 队列有两个端口,一个端口只能出数据,称为队首(head),一个端口只能进数据,称为队尾(tail)。
- 先入先出,后入后出。
3.其他
- 队列的控制元素
1)数据空间
2)容量
3)队首指针
4)队尾指针 - 队列的基本操作
1)入队列
2)出队列 - 队列的表示
1)线性存储结构----数组
2)非线性存储结构----链表
ps:队列和堆栈很像,但是结果决定功能,所以又有所不同。
二、队列工具的基本实现
1.数据结构的实现
关于队列工具的实现 ,相比于链表,数组构造起来应该更好些。
但是如果使用一般的一维数组,又似乎不太好用。
例如,当数列满的时候,需要一个数出队列,一个新数入队列,那么如何实现?难度要将所有数移动一下?不仅麻烦还效率低。所以这时候又使用到了循环数组
实现基本出入队列操作
通过tail 和head的值,我们可以知道队列里有几个值,当然也有些特殊
已知某队列容量为12;
head = 4; tail = 7时,队列共有多少个有效元素?
head = 7tail = 4时,队列中共有多少个有效元素?
公式:(tail一head+ capacity)%capacity
但是,如果tail和head相同时,到底是满队列?还是空队列?
此时,可以通过上一次操作作为标签来识别是否其数量。
所以最终的控制元素为:
typedef struct QUEUE{
void **data; //数据空间
int capacity;//容量
int head;//队首
int tail;//队尾
int lastEvent;//上一次操作标记
}QUEUE;
不要忘记boolean值的定义。有关void**data数据,详情介绍看数据结构与算法&堆栈工具
- 初始化队列空间
//初始化队列
boolean initQueue(QUEUE **queue, int capacity) {
if (NULL == queue || NULL != *queue || capacity <= 0) {
return FALSE;
}
*queue = (QUEUE *)calloc(sizeof(QUEUE), 1);
if (NULL == *queue) {
return FALSE;
}
(*queue)->data = (void **)calloc(sizeof(void *), capacity);
if (NULL == (*queue)->data) {
free(*queue);
*queue = NULL;
return FALSE;
}
(*queue)->capacity = capacity;
(*queue)->head = 0;
(*queue)->tail = 0;
(*queue)->lastEvent = OUT;//刚开始为空,状态为出
return TRUE;
}
- 销毁队列
//销毁队列
void destoryQueue(QUEUE **queue) {
if (NULL == queue || NULL == *queue) {
return;
}
free((*queue)->data);
free(*queue);
queue = NULL;
}
2.队列的一些基本功能实现
- 队列满?
//判断队列空
boolean isQueueEmpty(const QUEUE *queue) {
if (NULL == queue) {
return FALSE;
}
return OUT == queue->lastEvent && queue->head == queue->tail;
}
- 队列空
//判断队列满
boolean isQueueFull(const QUEUE *queue) {
if (NULL == queue) {
return FALSE;
}
return IN == queue->lastEvent && queue->head == queue->tail;
}
- 基本操作
//入队列
boolean in(QUEUE *queue, void *data) {
if (NULL == queue || isQueueFull(queue)) {
return FALSE;
}
queue->data[queue->tail] = data;
queue->tail = (queue->tail + 1) % queue->capacity;
queue->lastEvent = IN;
return TRUE;
}
//出队列
boolean out(QUEUE *queue, void **data) {
if (NULL == queue || NULL == data || isQueueEmpty(queue)) {
return FALSE;
}
*data = queue->data[queue->head];
queue->head = (queue->head + 1) % queue->capacity;
queue->lastEvent = OUT;
return TRUE;
}
- 读队首元素
//读取队首元素
boolean readQueueHead(QUEUE *queue, void **data) {
if (NULL == queue || NULL == data || isQueueEmpty(queue)) {
return FALSE;
}
*data = queue->data[queue->head];
return TRUE;
}
- 读取队列元素个数
//读取队列有效元素
int getCount(const QUEUE *queue) {
if (NULL == queue) {
return -1;
}
if (queue->tail == queue->head) {
return queue->lastEvent == IN ? queue->capacity : 0;
}
return (queue->tail - queue->head + queue->capacity) % queue->capacity;
}
三、总结
1.结构决定功能。功能的实现需要结构。
2.不要拖延!!!
笔者水平有限,目前只能描述以上问题,如果有其他情况,可以留言,有错误,请指教,有继续优化的,请分享,谢谢!
完整代码如下:
queue.h代码
#ifndef _SL_QUEUE_H_
#define _SL_QUEUE_H_
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
#define IN 1
#define OUT -1
typedef struct QUEUE{
void **data; //数据空间
int capacity;//容量
int head;//队首
int tail;//队尾
int lastEvent;//上一次操作标记
}QUEUE;
boolean initQueue(QUEUE **queue, int capacity);
void destoryQueue(QUEUE **queue);
boolean isQueueEmpty(const QUEUE *queue);
boolean isQueueFull(const QUEUE *queue);
boolean in(QUEUE *queue, void *data);
boolean out(QUEUE *queue, void **data);
boolean readQueueHead(QUEUE *queue, void **data);
int getCount(const QUEUE *queue);
#endif
queue.c代码
#include <stdio.h>
#include <malloc.h>
#include "queue.h"
//初始化队列
boolean initQueue(QUEUE **queue, int capacity) {
if (NULL == queue || NULL != *queue || capacity <= 0) {
return FALSE;
}
*queue = (QUEUE *)calloc(sizeof(QUEUE), 1);
if (NULL == *queue) {
return FALSE;
}
(*queue)->data = (void **)calloc(sizeof(void *), capacity);
if (NULL == (*queue)->data) {
free(*queue);
*queue = NULL;
return FALSE;
}
(*queue)->capacity = capacity;
(*queue)->head = 0;
(*queue)->tail = 0;
(*queue)->lastEvent = OUT;//刚开始为空,状态为出
return TRUE;
}
//销毁队列
void destoryQueue(QUEUE **queue) {
if (NULL == queue || NULL == *queue) {
return;
}
free((*queue)->data);
free(*queue);
queue = NULL;
}
//判断队列空
boolean isQueueEmpty(const QUEUE *queue) {
if (NULL == queue) {
return FALSE;
}
return OUT == queue->lastEvent && queue->head == queue->tail;
}
//判断队列满
boolean isQueueFull(const QUEUE *queue) {
if (NULL == queue) {
return FALSE;
}
return IN == queue->lastEvent && queue->head == queue->tail;
}
//入队列
boolean in(QUEUE *queue, void *data) {
if (NULL == queue || isQueueFull(queue)) {
return FALSE;
}
queue->data[queue->tail] = data;
queue->tail = (queue->tail + 1) % queue->capacity;
queue->lastEvent = IN;
return TRUE;
}
//出队列
boolean out(QUEUE *queue, void **data) {
if (NULL == queue || NULL == data || isQueueEmpty(queue)) {
return FALSE;
}
*data = queue->data[queue->head];
queue->head = (queue->head + 1) % queue->capacity;
queue->lastEvent = OUT;
return TRUE;
}
//读取队首元素
boolean readQueueHead(QUEUE *queue, void **data) {
if (NULL == queue || NULL == data || isQueueEmpty(queue)) {
return FALSE;
}
*data = queue->data[queue->head];
return TRUE;
}
//读取队列有效元素
int getCount(const QUEUE *queue) {
if (NULL == queue) {
return -1;
}
if (queue->tail == queue->head) {
return queue->lastEvent == IN ? queue->capacity : 0;
}
return (queue->tail - queue->head + queue->capacity) % queue->capacity;
}
2020.03.05 家