5.队列
一.Queue 基本概念
队列是一种特殊的线性表
队列仅在线性表的两端进行操作
队头(Front):取出数据元素的一端
队尾(Rear):插入数据元素的一端
队列不允许在中间部位进行操作!
常用操作
- 销毁队列
- 清空队列
- 进队列
- 出队列
- 获取队头元素
- 获取队列的长度
二.队列的顺序存储设计与实现
seqlist.h
#ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__ #define DLL_API __declspec(dllexport) //_declspec(dllexport):导出标志 typedef void SeqList; typedef void SeqListNode; // 创建线性表 DLL_API SeqList* SeqList_Create(int capacity); // 销毁线性表 DLL_API void SeqList_Destroy(SeqList *list); // 清空线性表 DLL_API void SeqList_Clear(SeqList *list); // 获得线性表的长度 DLL_API int SeqList_Length(SeqList *list); // 获得线性表的容量 DLL_API int SeqList_Capacity(SeqList *list); // 向线性表中插入一个元素 DLL_API int SeqList_Insert(SeqList *list, SeqListNode *node, int pos); // 获取线性表中某一个位置的元素 DLL_API SeqListNode* SeqList_Get(SeqList *list, int pos); // 删除线性表中某一个位置的元素 DLL_API SeqListNode* SeqList_Delete(SeqList *list, int pos); #endif
seqlist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "seqlist.h" typedef struct _tag_SeqList { int capacity; int length; unsigned int *node; // unsigned int array[capacity] }TSeqList; // 创建线性表 SeqList* SeqList_Create(int capacity) { TSeqList *ret = NULL; if (capacity < 0) { return NULL; } ret = malloc(sizeof(TSeqList) + sizeof(unsigned int)*capacity); if (ret == NULL) { return NULL; } memset(ret, 0, sizeof(TSeqList)+sizeof(unsigned int)*capacity); ret->node = (unsigned int *)(ret + 1); // ret 向后跳转sizeof(TSeqList) ret->capacity = capacity; ret->length = 0; return ret; } // 销毁线性表 void SeqList_Destroy(SeqList *list) { if (list != NULL) { free(list); } } // 清空线性表 void SeqList_Clear(SeqList *list) { TSeqList *tList = NULL; if (list == NULL) { return; } tList = (SeqList*)list; tList->length = 0; } // 获得线性表的长度 int SeqList_Length(SeqList *list) { TSeqList *tList = NULL; tList = (TSeqList*)list; if (tList == NULL) { return -1; } return tList->length; } // 获得线性表的容量 int SeqList_Capacity(SeqList *list) { TSeqList *tList = NULL; tList = (TSeqList*)list; if (tList == NULL) { return -1; } return tList->capacity; } // 向线性表中插入一个元素 DLL_API int SeqList_Insert(SeqList *list, SeqListNode *node, int pos) { int i = 0; TSeqList *tList = NULL; tList = (TSeqList*)list; // 保证传入的线性表和元素节点不能为NULL if (list == NULL || node == NULL) { return -1; } // 判断该线性表是否已满 if (tList->length >= tList->capacity) { return -2; } // 判断插入索引是否合法 if (pos < 0 || pos >= tList->capacity) { return -3; } // 若索引值大于线性表当前长度,则将元素插入到线性表的末尾 if (pos >= tList->length) { pos = tList->length; } // 插入算法 // 将pos位置后的元素移次向后移 for (i = tList->length; i > pos; i--) { // 更新后移元素的值 tList->node[i] = tList->node[i - 1]; } // 元素后移完毕后,将元素放到指定的位置 tList->node[pos] = (unsigned int)node; tList->length ++; return 0; } // 获取线性表中某一个位置的元素 SeqListNode* SeqList_Get(SeqList *list, int pos) { SeqListNode *ret = NULL; TSeqList *tList = NULL; tList = (TSeqList*)list; // 过滤非法参数 if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } ret = (SeqListNode*)tList->node[pos]; return ret; } // 删除线性表中某一个位置的元素 SeqListNode* SeqList_Delete(SeqList *list, int pos) { int i = 0; TSeqList *tList = NULL; SeqListNode *ret = NULL; tList = (TSeqList*)list; if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } 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.h
#ifndef __MY_SEQ_QUEUE_H__ #define __MY_SEQ_QUEUE_H__ typedef void SeqQueue; // 创建队列 SeqQueue* SeqQueue_Create(int capacity); // 销毁队列 void SeqQueue_Destroy(SeqQueue* queue); // 清空队列 void SeqQueue_Clear(SeqQueue* queue); // 向队尾添加元素 int SeqQueue_Append(SeqQueue* queue, void* item); // 移除队列头部元素 void* SeqQueue_Retrieve(SeqQueue* queue); // 获取队列头部元素 void* SeqQueue_Header(SeqQueue* header); // 获取队列长度 int SeqQueue_Length(SeqQueue* length); // 获取队列容量 int SeqQueue_Capacity(SeqQueue* queue); #endif
seqqueue.c
#include "seqqueue.h" #include "seqlist.h" // 创建队列 SeqQueue* SeqQueue_Create(int capacity) { return SeqList_Create(capacity); } // 销毁队列 void SeqQueue_Destroy(SeqQueue* queue) { SeqList_Destroy(queue); } // 清空队列 void SeqQueue_Clear(SeqQueue* queue) { SeqList_Clear(queue); } // 向队尾添加元素,相当于向线性表的尾部插入元素 int SeqQueue_Append(SeqQueue* queue, void* item) { return SeqList_Insert(queue, item, SeqList_Length(queue)); } // 移除队列头部元素 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); }
运行结果:
current queue capacity is: 10
current queue length is: 6
current student age is: 12
current new length is: 0
请按任意键继续. . .
三.队列的链式存储设计与实现
linklist.h
#ifndef __MY_LINKLIST_H__ #define __MY_LINKLIST_H__ #define DLL_API __declspec(dllexport) //_declspec(dllexport):导出标志 typedef void LinkList; typedef struct _tag_LinkListNode { struct _tag_LinkListNode* next; // 当前节点需要指向下一个节点的地址 }LinkListNode; DLL_API LinkList* LinkList_Create(); DLL_API void LinkList_Destroy(LinkList *list); DLL_API void LinkList_Clear(LinkList *list); DLL_API int LinkList_Length(LinkList *list); DLL_API int LinkList_Insert(LinkList *list, LinkListNode *node, int pos); DLL_API LinkListNode* LinkList_Get(LinkList *list, int pos); DLL_API LinkListNode* ListList_Delete(LinkList *list, int pos); #endif
linklist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "linklist.h" typedef struct _tag_LinkList { LinkListNode header; // 链表中需要包含一个头节点 int length; }TLinkList; // 创建链表 LinkList* LinkList_Create() { TLinkList *ret = (TLinkList*)malloc(sizeof(TLinkList)); if (ret == NULL) return NULL; memset(ret, 0, sizeof(TLinkList)); ret->header.next = NULL; ret->length = 0; return ret; } // 销毁链表 void LinkList_Destroy(LinkList *list) { if (list != NULL) { free(list); } } // 清空链表 void LinkList_Clear(LinkList *list) { TLinkList *tList = NULL; if (list == NULL) return; tList = (TLinkList*)list; tList->header.next = NULL; tList->length = 0; } // 获取当前链表长度 int LinkList_Length(LinkList *list) { TLinkList *tList = NULL; if (list == NULL) return -1; tList = (TLinkList*)list; return tList->length; } // 向当前链表插入数据 int LinkList_Insert(LinkList *list, LinkListNode *node, int pos) { TLinkList *tList = NULL; LinkListNode *current = NULL; int i = 0; tList = (TLinkList*)list; // 过滤非法参数 if (list == NULL || pos < 0) { return -1; } /* * 插入要点 *1.让新插入的元素节点指向原有位置的元素节点 *2.修改原有位置的前一个元素节点的指向(更新指向为新插入的元素节点) */ // 准备环境让辅助指针变量 指向链表头节点 current = &tList->header; // 将当前链表的节点移动到待插入节点的前一个节点的位置(假如待插入的位置是3,则移动到2号位置) for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; // 将辅助节点运动到指定位置(待插入位置的前一个节点) } // 让新插入的元素节点指向原有位置的元素节点 node->next = current->next; current->next = node; tList->length++; return 0; } LinkListNode* LinkList_Get(LinkList *list, int pos) { TLinkList *tList = NULL; int i = 0; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; // 过滤非法参数 if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } current = &tList->header; // 将辅助指针变量运行到待获取元素的前一个节点 for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; } ret = current->next; return ret; } LinkListNode* ListList_Delete(LinkList *list, int pos) { TLinkList *tList = NULL; tList = (TLinkList *)list; LinkListNode *current = NULL; LinkListNode *ret = NULL; int i = 0; // 过滤非法参数 if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } // 移动辅助指针变量 current = &tList->header; for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; } ret = current->next; // 将待删除位置的前一个节点的指向连接到删除位置节点的指向 current->next = ret->next; // 将链表长度-1 tList->length--; return ret; }
linkqueue.h
#ifndef __MY_LINK_QUEUE_H__ #define __MY_LINK_QUEUE_H__ typedef void LinkQueue; // 创建队列 LinkQueue* LinkQueue_Create(); // 销毁队列 void LinkQueue_Destroy(LinkQueue* queue); // 清空队列 void LinkQueue_Clear(LinkQueue* queue); // 向队尾添加元素 int LinkQueue_Append(LinkQueue* queue, void* item); // 删除队首元素 void* LinkQueue_Retrieve(LinkQueue* queue); // 获取队首元素 void* LinkQueue_Header(LinkQueue* header); // 获取当前队列长度 int LinkQueue_Length(LinkQueue* queue); #endif
linkqueue.c
#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_Destroy(LinkQueue* queue) { LinkQueue_Clear(queue); LinkList_Destroy(queue); } // 清空队列 void LinkQueue_Clear(LinkQueue* queue) { while (LinkQueue_Length(queue) > 0) { LinkQueue_Retrieve(queue); // 该函数包含内存释放函数 } } // 向队列中添加元素,相当于向队列的队尾添加元素 int LinkQueue_Append(LinkQueue* queue, void* item) { int ret = 0; TLinkQueueNode *node = NULL; node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode)); if (node == NULL) return -1; memset(node, 0, sizeof(TLinkQueueNode)); node->item = item; ret = LinkList_Insert(queue, (LinkListNode *)node, LinkList_Length(queue)); if (ret != 0) // 插入失败 { free(node); return ret; } return ret; } // 删除队首元素 void* LinkQueue_Retrieve(LinkQueue* queue) { void *ret = NULL; TLinkQueueNode *node = NULL; node = (TLinkQueueNode*)ListList_Delete(queue, 0); if (node == NULL) return NULL; ret = node->item; free(node); node = NULL; return ret; } // 获取队首元素 void* LinkQueue_Header(LinkQueue* queue) { void *ret = NULL; TLinkQueueNode *node = NULL; node = (TLinkQueueNode*)LinkList_Get(queue, 0); if (node == NULL) return NULL; ret = node->item; return ret; } // 获取当前队列长度 int LinkQueue_Length(LinkQueue* queue) { return LinkList_Length(queue); }
test.c
#include <stdio.h> #include <stdlib.h> #include "linkqueue.h" typedef struct _Student { char name[20]; int age; }Student; int main() { Student s1, s2, s3, s4, s5, s6; s1.age = 11; s2.age = 12; s3.age = 13; s4.age = 14; s5.age = 15; s6.age = 16; LinkQueue *queue = LinkQueue_Create(); if (queue != NULL) { LinkQueue_Append(queue, &s1); LinkQueue_Append(queue, &s2); LinkQueue_Append(queue, &s3); LinkQueue_Append(queue, &s4); LinkQueue_Append(queue, &s5); LinkQueue_Append(queue, &s6); printf("current queue length is: %d\n",LinkQueue_Length(queue)); printf("\n"); // 移除队首元素 LinkQueue_Retrieve(queue); Student *pStu = LinkQueue_Header(queue); printf("current header age is %d\n", pStu->age); printf("\n"); // 清空队列 LinkQueue_Clear(queue); int new_length = LinkQueue_Length(queue); printf("currnet queue new length is: %d\n",new_length); } system("pause"); return 0; }
运行结果:
current queue length is: 6
current header age is 12
currnet queue new length is: 0
请按任意键继续. . .