队列
队列是一种特殊的线性表
队列仅在线性表的两端进行操作
队头(Front):取出数据元素的一端
队尾(Rear):插入数据元素的一端
队列不允许在中间部位进行操作!
队列也是一种特殊的线性表
1 队列顺序存储结构
seqlist.h
#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__
typedef void SeqList;
typedef void SeqListNode;
// 创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity);
// 销毁一个线性表list
void SeqList_Destory(SeqList* list);
// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list);
// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list);
int SeqList_Capacity(SeqList* list);
// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos);
// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos);
#endif
seqqueue.h
#ifndef _MY_SEQQUEUE_H_
#define _MY_SEQQUEUE_H_
typedef void SeqQueue;
SeqQueue* SeqQueue_Create(int capacity);
void SeqQueue_Destory(SeqQueue* queue);
void SeqQueue_Clear(SeqQueue* queue);
int SeqQueue_Append(SeqQueue* queue, void* item);
void* SeqQueue_Retrieve(SeqQueue* queue);
void* SeqQueue_Header(SeqQueue* queue);
int SeqQueue_Length(SeqQueue* queue);
int SeqQueue_Capacity(SeqQueue* queue);
#endif _MY_SEQQUEUE_H_
seqlist.c
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"seqlist.h"
//结构体套一级指针
typedef struct _tag_SeqList {
int length;
int capacity;
unsigned int** node; //int *node[] 指针数组
}TSeqList;
SeqList* SeqList_Create(int capacity) {
TSeqList* tmp = NULL;
tmp = (TSeqList*)malloc(sizeof(TSeqList));
if (tmp == NULL) {
printf("func SeqList_Create() error");
return NULL;
}
memset(tmp, 0, sizeof(TSeqList));
//根据capacity大小分配节点空间
tmp->node = (unsigned int**)malloc(sizeof(unsigned int*) * capacity);
if (tmp->node == NULL) {
printf("func SeqList_Create() tmp->node error ");
return NULL;
}
tmp->capacity = capacity;
tmp->length = 0;
return tmp;
}
// 销毁一个线性表list
void SeqList_Destory(SeqList* list) {
TSeqList* tlist = NULL;
if (list == NULL) {
return;
}
tlist = (TSeqList*)list;
if (tlist->node != NULL) {
free(tlist->node);
}
free(tlist);
}
// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list) {
TSeqList* tlist = NULL;
if (list == NULL) {
return;
}
tlist = (TSeqList*)list;
tlist->length = 0;
}
// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list) {
TSeqList* tlist = NULL;
if (list == NULL) {
return -1;
}
tlist = (TSeqList*)list;
return tlist->length;
}
int SeqList_Capacity(SeqList* list) {
TSeqList* tlist = NULL;
if (list == NULL) {
return -1;
}
tlist = (TSeqList*)list;
return tlist->capacity;
}
// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) {
int i = 0, ret = 0;
TSeqList* tlist = NULL;
if (list == NULL || node==NULL || pos < 0) {
ret = -1;
printf("SeqList_Insert() error : %d\n", ret);
return ret;
}
tlist = (TSeqList*)list;
//判断是不是链表空间满了
if (tlist->length == tlist->capacity) {
ret = -2;
printf("SeqList_Insert() tlist->length == tlist->capacity error : %d\n", ret);
return ret;
}
// 容错修正 长度为6,容量为20, 在pos=10插入,可以改为插入7位置
if (pos >= tlist->length) {
pos = tlist->length;
}
// 元素后移
for (i = tlist->length; i > pos; i--) {
tlist->node[i] = tlist->node[i-1];
}
// 元素插入
tlist->node[i] = node;
tlist->length++;
return 0;
}
// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos) {
int i = 0;
SeqListNode* ret = 0;
TSeqList* tlist = NULL;
if (list == NULL || pos < 0) {
printf("SeqList_Get() error : %d\n", ret);
return NULL;
}
tlist = (TSeqList*)list;
ret = (SeqListNode*)tlist->node[pos];
return ret;
}
// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos) {
int i = 0;
SeqListNode* ret = 0;
TSeqList* tlist = NULL;
if (list == NULL || pos < 0) {
printf("SeqList_Delete() error : %d\n", ret);
return NULL;
}
tlist = (TSeqList*)list;
ret = (SeqListNode*)tlist->node[pos];
for (i = pos + 1; i < tlist->length; i++) {
tlist->node[i-1] = tlist->node[i];
}
tlist->length--;
return ret;
}
seqqueue.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"seqqueue.h"
#include"seqlist.h"
//队列是一种特殊的线性表
// 创建一个队列相当于创建一个顺序存储线性表
SeqQueue* SeqQueue_Create(int capacity){
return SeqList_Create(capacity);
}
// 销毁队列相当于销毁一个线性表
void SeqQueue_Destory(SeqQueue* queue) {
SeqList_Destory(queue);
}
// 清空队列相当于清空线性表
void SeqQueue_Clear(SeqQueue* queue) {
SeqList_Clear(queue);
}
// 向队列中添加一个元素相当于向线性表中添加一个元素
int SeqQueue_Append(SeqQueue* queue, void* item) {
return SeqList_Insert(queue, item, SeqList_Length(queue));
}
// 出队列相当于从线性表中删除0号位置元素
void* SeqQueue_Retrieve(SeqQueue* queue) {
return SeqList_Delete(queue, 0);
}
void* SeqQueue_Header(SeqQueue* queue) {
return SeqList_Get(queue, 0);
}
int SeqQueue_Length(SeqQueue* queue) {
return SeqList_Length(queue);
}
int SeqQueue_Capacity(SeqQueue* queue) {
return SeqList_Capacity(queue);
}
队列顺序存储实现.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"seqqueue.h"
void main() {
int i = 0, ret = 0;
int a[10];
SeqQueue* queue = NULL;
queue = SeqQueue_Create(10);
if (queue == NULL) {
return;
}
// 入队列
for (i = 0; i < 5; i++) {
a[i] = i + 1;
ret = SeqQueue_Append(queue, &a[i]);
}
// 打印队列属性
printf("len: %d\n", SeqQueue_Length(queue));
printf("head element : %d\n", *((int*)SeqQueue_Header(queue)));
printf("capacity : %d\n", SeqQueue_Capacity(queue));
// 出队列
while (SeqQueue_Length(queue) > 0) {
int tmp = *((int*)SeqQueue_Retrieve(queue));
printf("tmp: %d ", tmp);
}
SeqQueue_Destory(queue);
}
另一种实现方法,不是基于线性表
SqQueue.h
#ifndef _SQQUEUE_H
#define _SQQUEUE_H
#define MAXSIZE 20
typedef struct
{
// 队头
int front;
// 队尾, 指向数组的最后一个元素
int rear;
// 数据
void* data[MAXSIZE];
}SqQueue;
// 初始化操作,建立一个空队列Q
void InitQueue(SqQueue *Q);
// 将队列Q清空
void ClearQueue(SqQueue *Q);
// 若队列为空则返回true,否则返回false
int QueueEmpty(SqQueue Q);
// 若队列Q存在且非空,用e返回队列Q的队头元素
void GetHead(SqQueue Q, void** e);
// 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
void EnQueue(SqQueue *Q, void* e);
// 删除队列Q中的队头元素,并用e返回其值
void DeQueue(SqQueue *Q, void** e);
// 返回队列Q的元素个数
int QueueLength(SqQueue Q);
#endif //_SQQUEUE_H
SqQueue.c
#include "SqQueue.h"
#include <string.h>
void InitQueue(SqQueue *Q)
{
// 空队列
Q->front = -1;
Q->rear = -1;
memset(Q->data, 0, sizeof(Q->data));
}
void ClearQueue(SqQueue *Q)
{
Q->front = -1;
Q->rear = -1;
}
int QueueEmpty(SqQueue Q)
{
if (Q.front == -1)
{
return 1;
}
return 0;
}
// 数组的头部为队头, 尾部为队尾
void GetHead(SqQueue Q, void** e)
{
// 错误处理
if (Q.front == -1)
{
// 空队列
return;
}
*e = Q.data[Q.front];
}
void EnQueue(SqQueue *Q, void* e)
{
if (Q->rear == MAXSIZE - 1)
{
// 队列已满
return;
}
// 添加第一个的时候
if (Q->front == -1)
{
Q->front = 0;
}
// 尾部+1
Q->rear++;
Q->data[Q->rear] = e;
}
void DeQueue(SqQueue *Q, void** e)
{
if (Q->front == -1)
{
return;
}
// 保存队头元素
*e = Q->data[Q->front];
// 从1到最后依次前移
for (int i = 1; i <= Q->rear; ++i)
{
Q->data[i - 1] = Q->data[i];
}
// 队尾前移
Q->rear--;
if (Q->rear == -1)
{
Q->front = -1;
}
}
int QueueLength(SqQueue Q)
{
return Q.rear+1;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include"SqQueue.h"
void main()
{
int array[10];
// 创建队列变量
SqQueue q;
// 初始化队列
InitQueue(&q);
//
for (int i = 0; i < 10; ++i)
{
array[i] = i + 10;
// 入队列
EnQueue(&q, (void*)&array[i]);
}
printf("Queeu size = %d\n", QueueLength(q));
// 全部都出队列
while (QueueEmpty(q) != 1)
{
int* tmp;
GetHead(q, (void**)&tmp);
printf("Queue head value = %d\n", *tmp);
// 出队列
DeQueue(&q, (void**)&tmp);
printf("Delete elem value = %d\n", *tmp);
}
}
结果
Queeu size = 10
Queue head value = 10
Delete elem value = 10
Queue head value = 11
Delete elem value = 11
Queue head value = 12
Delete elem value = 12
Queue head value = 13
Delete elem value = 13
Queue head value = 14
Delete elem value = 14
Queue head value = 15
Delete elem value = 15
Queue head value = 16
Delete elem value = 16
Queue head value = 17
Delete elem value = 17
Queue head value = 18
Delete elem value = 18
Queue head value = 19
Delete elem value = 19
2 队列链式存储结构
linklist.h
#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_
typedef void LinkList;
/*
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode{
LinkListNode *next;
}
*/
typedef struct _tag_LinkListNode {
struct _tag_LinkListNode* next;
}LinkListNode;
LinkList* LinkList_Create();
void LinkList_Destory(LinkList* list);
void LinkList_Clear(LinkList* list);
int LinkList_Length(LinkList* list);
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
LinkListNode* LinkList_Get(LinkList* list, int pos);
LinkListNode* LinkList_Delete(LinkList* list, int pos);
#endif
linkqueue.h
#ifndef _MY_LINKQUEUE_H_
#define _MY_LINKQUEUE_H_
typedef void LinkQueue;
LinkQueue* LinkQueue_Create();
void LinkQueue_Destory(LinkQueue* queue);
void LinkQueue_Clear(LinkQueue* queue);
int LinkQueue_Append(LinkQueue* queue, void *item);
void* LinkQueue_Retrieve(LinkQueue* queue);
void* LinkQueue_Header(LinkQueue* queue);
int LinkQueue_Length(LinkQueue* queue);
#endif // !_MY_LINKQUEUE_H_
linklist.c
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"linklist.h"
typedef struct _tag_LinkList {
LinkListNode head;
int length;
}TLinkList;
LinkList* LinkList_Create() {
TLinkList* ret = NULL;
ret = (TLinkList*)malloc(sizeof(TLinkList));
memset(ret, 0, sizeof(TLinkList));
ret->length = 0;
ret->head.next = NULL;
return ret;
}
void LinkList_Destory(LinkList* list) {
if (list != NULL) {
free(list);
list = NULL;
}
return;
}
// 让链表变为初始值
void LinkList_Clear(LinkList* list) {
TLinkList* tList = 0;
if (list == NULL) {
return;
}
tList = (TLinkList*)list;
tList->length = 0;
tList->head.next = NULL;
return;
}
int LinkList_Length(LinkList* list) {
TLinkList* tList = 0;
if (list == NULL) {
return;
}
tList = (TLinkList*)list;
return tList->length;
}
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) {
int ret = 0, i = 0;
TLinkList* tList = NULL;
LinkListNode* current = NULL;
if (list == NULL || node == NULL || pos < 0) {
ret = -1;
printf("LinkList_Insert error %d\n",ret);
return ret;
}
tList = (TLinkList*)list;
current = &(tList->head);
for (i = 0; i < pos && current->next != NULL; i++) {
current = current->next;
}
// 1 node连接后续链表
node->next = current->next;
// 2 前面链表连接新的链表
current->next = node;
tList->length++;
return ret;
}
LinkListNode* LinkList_Get(LinkList* list, int pos) {
int i = 0;
TLinkList* tList = NULL;
LinkListNode* current = NULL;
if (list == NULL || pos < 0) {
printf("LinkList_Get error %d\n");
return NULL;
}
tList = (TLinkList*)list;
current = &(tList->head); //辅助指针变量指向链表头部
for (i = 0; i < pos && current->next != NULL; i++) {
current = current->next;
}
return current->next;
}
LinkListNode* LinkList_Delete(LinkList* list, int pos) {
int i = 0;
TLinkList* tList = NULL;
LinkListNode* current = NULL;
LinkListNode* ret = NULL;
if (list == NULL || pos < 0) {
printf("LinkList_Delete error \n");
return NULL;
}
tList = (TLinkList*)list;
current = &(tList->head);
for (i = 0; i < pos && current->next != NULL; i++) {
current = current->next;
}
// 缓存被删除节点
ret = current->next;
current->next = ret->next;
tList->length--;
return ret;
}
linkqueue.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkqueue.h"
#include"linklist.h"
// 队列也是一种特殊的线性表
// 队列业务节点的数据结构
typedef struct _tag_LinkQueueNode {
LinkListNode node;
void* item;
}TLinkQueueNode;
// 创建队列 相当于创建线性表
LinkQueue* LinkQueue_Create() {
return LinkList_Create();
}
// 销毁队列 相当于销毁线性表
// 节点的内存管理
void LinkQueue_Destory(LinkQueue* queue) {
LinkQueue_Clear(queue);
LinkList_Destory(queue);
}
// 如果清空队列 需要显式的把队列中的所有节点 选出来
// 释放每一个节点
void LinkQueue_Clear(LinkQueue* queue) {
while (LinkQueue_Length(queue) > 0) {
LinkQueue_Retrieve(queue);
}
LinkList_Clear(queue);
}
// 向队列中添加元素相当于向线性表的尾部添加元素
int LinkQueue_Append(LinkQueue* queue, void* item) {
int ret = 0;
TLinkQueueNode* tmp = NULL;
tmp = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));
if (tmp == NULL) {
ret = -1;
printf("LinkQueue_Append error malloc %d\n",ret);
return ret;
}
memset(tmp, 0, sizeof(TLinkQueueNode));
tmp->item = item;
// 需要把栈的item业务节点转化成链表的LinklistNode业务节点
ret = LinkList_Insert(queue, (LinkListNode*)tmp, LinkList_Length(queue));
if (ret != 0) {
ret = 3;
printf("LinkList_Insert error %d\n", ret);
if (tmp != NULL)free(tmp);
return ret;
}
return ret;
}
// 从队列中删除元素 相当于从线性表的头部删除元素
void* LinkQueue_Retrieve(LinkQueue* queue) {
void* ret = NULL;
TLinkQueueNode* tmp = NULL;
tmp = (TLinkQueueNode*)LinkList_Delete(queue, 0);
if (tmp == NULL) {
printf("func LinkList_Delete error\n");
return ret;
}
ret = tmp->item;
// 删除之前缓存
if (tmp != NULL) {
free(tmp);
}
return ret;
}
// 获取队列头部元素相当于从线性表0号位置拿数据
void* LinkQueue_Header(LinkQueue* queue) {
void* ret = NULL;
TLinkQueueNode* tmp = NULL;
tmp = (TLinkQueueNode*)LinkList_Get(queue, 0);
if (tmp == NULL) {
printf("func LinkList_Get error\n");
return ret;
}
return tmp->item;
}
// 求队列长度相当于求链表长度
int LinkQueue_Length(LinkQueue* queue) {
return LinkList_Length(queue);
}
队列链式存储测试.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkqueue.h"
void main() {
int i, a[10];
LinkQueue* queue = NULL;
queue = LinkQueue_Create();
if (queue == NULL) {
return;
}
// 向队列中添加元素
for (i = 0; i < 5; i++) {
a[i] = i + 1;
LinkQueue_Append(queue, &a[i]);
}
// 求队列的属性
printf("len:%d \n", LinkQueue_Length(queue));
printf("header:%d \n", *(int*)LinkQueue_Header(queue));
// 出队列
while (LinkQueue_Length(queue) > 0) {
int tmp = *((int*)LinkQueue_Retrieve(queue));
printf("tmp %d ", tmp);
}
// 销毁队列
LinkQueue_Destory(queue);
}
结果
len:5
header:1
tmp 1 tmp 2 tmp 3 tmp 4 tmp 5
另一种方法,不基于线性表的链式存储
LinkQueue.h
#ifndef _LINKQUEUE_H
#define _LINKQUEUE_H
typedef struct _NODE
{
struct _NODE* next;
}Node;
typedef struct
{
// 长度
int length;
// 尾节点指针
Node *real;
// 头结点指针
Node *front;
}LinkQueue;
// 初始化操作,建立一个空队列Q
void InitQueue(LinkQueue *Q);
// 将队列Q清空
void ClearQueue(LinkQueue *Q);
// 若队列为空则返回true,否则返回false
int QueueEmpty(LinkQueue Q);
// 若队列Q存在且非空,用e返回队列Q的队头元素
void GetHead(LinkQueue Q, Node** e);
// 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
void EnQueue(LinkQueue *Q, Node* e);
// 删除队列Q中的队头元素,并用e返回其值
void DeQueue(LinkQueue *Q, Node** e);
// 返回队列Q的元素个数
int QueueLength(LinkQueue Q);
#endif //_LINKQUEUE_H
LinkQueue.c
#include "LinkQueue.h"
#include <stdio.h>
void InitQueue(LinkQueue *Q)
{
Q->length = 0;
Q->real = NULL;
Q->front = NULL;
}
void ClearQueue(LinkQueue *Q)
{
while (Q->length)
{
Node* p;
DeQueue(Q, &p);
}
}
int QueueEmpty(LinkQueue Q)
{
if (Q.length == 0)
{
return 1;
}
return 0;
}
// 链表的头部为队头, 尾部为队尾
void GetHead(LinkQueue Q, Node** e)
{
// 错误处理
if (Q.length == 0)
{
return;
}
*e = Q.front;
}
void EnQueue(LinkQueue *Q, Node* e)
{
if (Q->length == 0)
{
// 空链表
Q->real = Q->front = e;
}
else
{
// 新节点放到队尾
Q->real->next = e;
// rear指向最后一个节点
Q->real = e;
}
// 长度
Q->length++;
}
void DeQueue(LinkQueue *Q, Node** e)
{
if (Q->length == 0)
{
// 空链表
return;
}
// 赋值
*e = Q->front;
// front指针后移
Q->front = Q->front->next;
// 长度
Q->length--;
if (Q->length == 0)
{
// 删除最后一个节点的时候, 尾指针需要指向NULL
Q->real = NULL;
}
}
int QueueLength(LinkQueue Q)
{
return Q.length;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include"LinkQueue.h"
void main()
{
// 业务节点
typedef struct _tag_value
{
// 包含一个链表节点
Node node;
// 数据
int v;
}Value;
Value val[5];
// 队列变量
LinkQueue q;
// init
InitQueue(&q);
//
for (int i = 0; i < 5; ++i)
{
val[i].v = i + 20;
// 入队列
EnQueue(&q, &val[i].node);
}
printf("Queue size = %d\n", QueueLength(q));
// 删除全部节点
while (QueueEmpty(q) != 1)
{
// 取出队头元素
Node* p;
GetHead(q, &p);
Value* pp = (Value*)p;
printf("Queue head value = %d\n", pp->v);
// 出队列
DeQueue(&q, &p);
pp = (Value*)p;
printf("Delete Queue head value = %d\n", pp->v);
}
}
结果
Queue size = 5
Queue head value = 20
Delete Queue head value = 20
Queue head value = 21
Delete Queue head value = 21
Queue head value = 22
Delete Queue head value = 22
Queue head value = 23
Delete Queue head value = 23
Queue head value = 24
Delete Queue head value = 24