队列
基本操作:入队列、出队列、取队首元素;
基本特性:先进先出;
1.顺序队列:
实现顺序队列时,我们利用数组实现,定义了head,tail用来记录当前首元素和最后元素的下标。但是在删除时,因为队列要实现“先进先出”,所以进行头删。所以本来数组的下标为[0,MAXSIZE),原本的head应该为0,但头删之后就不为0。在tail等于或大于MASIZE值时,若head不为0,则可以从0再继续入队列,即只要tail没有追上head就可以继续向队列里放元素;同样地,在打印队列元素以检查操作是否正确时,也要考虑这个因素。
SeqQueue.h
#pragma once #include <stdio.h> #include <stddef.h> #define SHOW_NAME printf("\n=================%s==================\n",__FUNCTION__); #define MAX_SIZE 5 typedef char SeqQueueType; typedef struct SeqQueue//整个队列的元素是从head到tail, { //由于出队是头删,所以前面可能会有空,所以当tail走到最后时,tail再指向0,只要size与MAX_SIZE不相等,就还有空间 SeqQueueType data[MAX_SIZE]; size_t head;//队列第一个元素下标 size_t tail;//队列最后一个元素的下标 size_t size;//用了多少个元素的空间 }SeqQueue;
SeqQueue.c
include "SeqQueue.h" void SeqQueueInit(SeqQueue* q)//初始化 { if(q == NULL)//非法操作 return; q->size = 0; q->head = 0; q->tail = 0; return; } void SeqQueueDestroy(SeqQueue* q)//销毁队列 { if(q == NULL) return; q->size = 0; q->head = 0; q->tail = 0; return; } void SeqQueuePush(SeqQueue* q,SeqQueueType value)//入队列(尾插) { if(q == NULL) return; if(q->size >= MAX_SIZE)//队列已满 return; q->data[q->tail++] = value; if(q->tail >= MAX_SIZE)//tail走到最后,就再指向头(只要size<MAX_SIZE) q->tail = 0; q->size++; return; } void SeqQueuePop(SeqQueue* q)//出列队(头删) { if(q == NULL)//非法操作 return; if(q->size == 0)//空队 return; q->head++; if(q->head >= MAX_SIZE)//别忘记!!! q->head = 0; q->size--; return; } int SeqQueueGetFront(SeqQueue* q,SeqQueueType* value)//取队首元素 { if(q == NULL) return 0; if(q->size == 0) return 0; *value = q->data[q->head]; return 1; } void SeqQueuePrint(SeqQueue* q,const char* msg)//打印 { printf("[%s]\n",msg); if(q == NULL) return; if(q->size == 0)//空队列 { printf("空队\n"); return; } size_t i = q->head; if(q->tail <= q->head)//tail在head前 { for(; i<MAX_SIZE; ++i) printf("[%c] ",q->data[i]); for(i=0; i<q->tail; ++i)//q->tail指向最后一个元素的下一个位置 printf("[%c] ",q->data[i]); } else//tail在head后 { for(i=q->head; i<q->tail; ++i) printf("[%c] ",q->data[i]); } printf("\n"); return; } void TestInit() { SHOW_NAME; SeqQueue q; SeqQueueInit(&q); printf("size: excpted is 0,actual is %d\n",q.size); printf("head: excpted is 0,actual is %d\n",q.head); printf("tail: excpted is 0,actual is %d\n",q.tail); } void TestDestroy() { SHOW_NAME; SeqQueue q; SeqQueueInit(&q); SeqQueueDestroy(&q); } void TestPush() { SHOW_NAME; SeqQueue q; SeqQueueInit(&q); SeqQueuePush(&q,'a'); SeqQueuePush(&q,'b'); SeqQueuePush(&q,'c'); SeqQueuePush(&q,'d'); SeqQueuePush(&q,'e'); SeqQueuePrint(&q,"入队五个元素"); } void TestPop() { SHOW_NAME; SeqQueue q; SeqQueueInit(&q); SeqQueuePush(&q,'a'); SeqQueuePush(&q,'b'); SeqQueuePush(&q,'c'); SeqQueuePush(&q,'d'); SeqQueuePush(&q,'e'); SeqQueuePrint(&q,"入队五个元素"); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePrint(&q,"出队三个元素"); SeqQueuePush(&q,'f'); SeqQueuePush(&q,'g'); SeqQueuePush(&q,'h'); SeqQueuePrint(&q,"入队三个元素"); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePrint(&q,"出队三个元素"); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePrint(&q,"出队两个元素"); } void TestGetFront() { SHOW_NAME; SeqQueue q; SeqQueueInit(&q); SeqQueuePush(&q,'a'); SeqQueuePush(&q,'b'); SeqQueuePush(&q,'c'); SeqQueuePrint(&q,"入队三个元素"); int ret = 0; SeqQueueType value; ret = SeqQueueGetFront(&q,&value); if(ret == 1) printf("取得队首元素为 %c\n",value); else printf("未取得队首元素\n"); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePop(&q); SeqQueuePrint(&q,"出队三个元素"); ret = SeqQueueGetFront(&q,&value); if(ret == 1) printf("取得队首元素为 %c\n",value); else printf("未取得队首元素\n"); } int main() { TestInit(); TestDestroy(); TestPush(); TestPop(); TestGetFront(); return 0; }
2.链式队列:
类似单链表实现链式队列
LinkQueue.h
#pragma once #include <stdio.h> #include <stddef.h> #include <stdlib.h> #define SHOW_NAME printf("\n=================%s==================\n",__FUNCTION__); typedef char LinkNodeType; typedef struct LinkNode { LinkNodeType data; struct LinkNode* next; }LinkNode; typedef struct LinkQueue//入队(尾插)、出队(头删) { LinkNode* head; LinkNode* tail; }LinkQueue;
LinkQueue.c
#include "LinkQueue.h" void LinkQueueInit(LinkQueue* q)//初始化 { if(q == NULL)//非法输入 return; q->head = NULL; q->tail =NULL; } void LinkQueueDestroy(LinkQueue* q)//销毁队列 { if(q == NULL) return; LinkNode* cur = q->head; while(cur != NULL) { LinkNode* to_delete = cur; cur = cur->next; free(to_delete); } q->head = q->tail = NULL; return; } LinkNode* CreateNode(LinkNodeType value)//新建一个结点 { LinkNode* new_node = (LinkNode*)malloc(sizeof(LinkNode)); new_node->data = value; new_node->next = NULL; return new_node; } void LinkQueuePush(LinkQueue* q,LinkNodeType value)//入队列(尾插) { if(q == NULL)//非法操作 return; if(q->head==NULL)//空队列 { q->head = q->tail = CreateNode(value); return; } LinkNode* p = CreateNode(value); q->tail->next = p; q->tail = q->tail->next; return; } void LinkQueuePop(LinkQueue* q)//出列队(头删) { if(q == NULL)//非法操作 return; if(q->tail == NULL)//空队 return; if(q->head->next == NULL)//只剩一个元素 { q->head = q->tail = NULL; return; } LinkNode* ret = q->head->next; q->head = ret; return; } int LinkQueueGetFront(LinkQueue* q,LinkNodeType* value)//取队首元素 { if(q == NULL) return 0; if(q->tail == NULL) return 0; *value = q->head->data; return 1; } void LinkQueuePrint(LinkQueue* q,const char* msg)//打印 { printf("[%s]\n",msg); LinkNode* cur = q->head; for(; cur!=NULL; cur=cur->next) { printf("[%c] ",cur->data); } printf("\n"); return; } void TestInit() { SHOW_NAME; LinkQueue q; LinkQueueInit(&q); } void TestDestroy() { SHOW_NAME; LinkQueue q; LinkQueueInit(&q); LinkQueueDestroy(&q); } void TestPush() { SHOW_NAME; LinkQueue q; LinkQueueInit(&q); LinkQueuePush(&q,'a'); LinkQueuePush(&q,'b'); LinkQueuePush(&q,'c'); LinkQueuePush(&q,'d'); LinkQueuePush(&q,'e'); LinkQueuePrint(&q,"入队五个元素"); } void TestPop() { SHOW_NAME; LinkQueue q; LinkQueueInit(&q); LinkQueuePush(&q,'a'); LinkQueuePush(&q,'b'); LinkQueuePush(&q,'c'); LinkQueuePush(&q,'d'); LinkQueuePush(&q,'e'); LinkQueuePrint(&q,"入队五个元素"); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePrint(&q,"出队三个元素"); LinkQueuePush(&q,'f'); LinkQueuePush(&q,'g'); LinkQueuePush(&q,'h'); LinkQueuePrint(&q,"入队三个元素"); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePrint(&q,"出队三个元素"); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePrint(&q,"出队两个元素"); } void TestGetFront() { SHOW_NAME; LinkQueue q; LinkQueueInit(&q); LinkQueuePush(&q,'a'); LinkQueuePush(&q,'b'); LinkQueuePush(&q,'c'); LinkQueuePrint(&q,"入队三个元素"); int ret; LinkNodeType value; ret = LinkQueueGetFront(&q,&value); if(ret == 1) printf("取得队首元素为 %c\n",value); else printf("未取得队首元素\n"); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePop(&q); LinkQueuePrint(&q,"出队三个元素"); ret = LinkQueueGetFront(&q,&value); if(ret == 1) printf("取得队首元素为 %c\n",value); else printf("未取得队首元素\n"); } int main() { TestInit(); TestDestroy(); TestPush(); TestPop(); TestGetFront(); return 0; }