队列:生活中也会经常遇到的场景。即只允许在一端进行数据的插入操作,另一端进行数据的删除操作的特殊线性表。
插入的一端一般为队尾(即为入队);删除的一端则为队首(即出队)。具有
先进先出(FIFO)的特性。
在这儿,我写了2种队列:顺序队和链式队。
先来说说顺序队:出队的方法:①队头不变,出队后所有元素向前移动;②不移动元素,每删除一个元素,队头就向后移动一个元素。
①队头位置不变:如下图所示:
缺点:如果元素数量很多时,就要大批大批的移动数据。
②队头位置不变:
缺点:删除元素后,原来对头的位置就会浪费。并且再有元素入队时,就会发生溢出现象。
结合这两种删除所带来的麻烦,所以就有了循环队列。即不会大量的移动元素,也不会发生溢出现象,不会浪费空间。
如下图所示:判队空
缺点:虽然循环队列对于前面的两种有所提高,但是当插入的元素大于最大的队列个数是依然会溢出。
下面是顺序队的代码实现:
#pragma once #define TEST_HEADER printf("\n==================%s================\n",__FUNCTION__) typedef char QueueType; #define MaxQueue 1000 //定义队最大可以容纳1000个元素 typedef struct SeqQueue { QueueType data[MaxQueue]; size_t head; size_t tail; size_t size; }SeqQueue; SeqQueue q; void SeqQueueInit(SeqQueue* q);//初始化队列 void SeqQueueDestroy(SeqQueue* q); //销毁队列 void SeqQueuePush(SeqQueue* q,QueueType value);//入队 void SeqQueuePop(SeqQueue* q);//出队 int SeqQueueTop(SeqQueue* q,QueueType* top);//找队首元素
#include<stdio.h> #include"seqqueue.h" void SeqQueueInit(SeqQueue* q) { if(q == NULL) { //非法输入 return; } q->head = 0; q->tail = 0; q->size = 0; } void SeqQueueDestroy(SeqQueue* q) { if(q == NULL) { //非法输入 return; } q->head = 0; q->tail = 0; q->size = 0; } void SeqQueuePush(SeqQueue* q,QueueType value) { if(q == NULL) { //非法输入 return; } if(q->size >= MaxQueue) { return; } if(q->head == 0) { q->head = q->tail = value; } q->data [q->tail ++] = value; ++q->size ; if(q->tail >= MaxQueue) { q->tail = 0; } } void SeqQueuePop(SeqQueue* q) { if(q == NULL) { return; } if(q->head == 0) { //空队列 return; } ++q->head ; if(q->head >= MaxQueue) { q->head = 0; } } int SeqQueueTop(SeqQueue* q,QueueType* top) { if(q == NULL) { return 0; } if(q->head == 0) { return 0; } *top = q->data [q->head ]; return 1; }
#include<stdio.h> #include"seqqueue.h" void TEST_SeqQueue() { QueueType temp = 0; TEST_HEADER; SeqQueueInit(&q); SeqQueuePush(&q,'a'); SeqQueuePush(&q,'b'); SeqQueuePush(&q,'c'); SeqQueuePush(&q,'d'); SeqQueueTop(&q,&temp); printf("top expect is a ,actual is %c\n",temp); SeqQueuePop(&q); SeqQueueTop(&q,&temp); printf("top expect is b ,actual is %c\n",temp); SeqQueuePop(&q); SeqQueueTop(&q,&temp); printf("top expect is c ,actual is %c\n",temp); SeqQueuePop(&q); SeqQueueTop(&q,&temp); printf("top expect is d ,actual is %c\n",temp); SeqQueuePop(&q); } //////////////////test///////////////////// int main() { TEST_SeqQueue(); return 0; }
当循序队中元素的个数大于定义的队的最大元素时就会溢出,但是链式队是不会存在这个问题的。
下面是链式队:
#pragma once #define TEST_HEADER printf("\n===============%s============\n",__FUNCTION__) typedef char QueueNodeType; typedef struct LinkQueueNode { struct LinkQueueNode* next; QueueNodeType data; }LinkQueueNode; typedef struct LinkQueue { LinkQueueNode* head; LinkQueueNode* tail; }LinkQueue; LinkQueue q; void LinkQueueInit(LinkQueue* q); void LinkQueuePush(LinkQueue* q,QueueNodeType value); void LinkQueuePop(LinkQueue* q); int LinkQueueTop(LinkQueue* q,QueueNodeType* top);
#include<stdio.h> #include"LinkQueue.h" #include<stdio.h> #include<stdlib.h> void LinkQueueInit(LinkQueue* q) { if(q == NULL) { //非法输入 return; } q->head = NULL; q->tail = NULL; } LinkQueueNode* CreateLinkNode(QueueNodeType value) { LinkQueueNode* new_node = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); new_node->data = value; new_node->next = NULL; return new_node; } void LinkQueuePush(LinkQueue* q,QueueNodeType value) { LinkQueueNode* new_node = NULL; if(q == NULL) { return; } new_node = CreateLinkNode(value); if(q->head == NULL) { q->head = q->tail = new_node; return; } q->tail->next = new_node; q->tail = q->tail ->next; } void DestroyNode(LinkQueueNode* ptr) { free(ptr); } void LinkQueuePop(LinkQueue* q) { LinkQueueNode* to_deleted = NULL; if(q == NULL) { //非法输入 return; } if(q->head == NULL) { //空队列 return; } to_deleted = q->head ; if(q->head == q->tail ) { DestroyNode(to_deleted); q->head = q->tail = NULL; return; } q->head = to_deleted->next; DestroyNode(to_deleted); } int LinkQueueTop(LinkQueue* q,QueueNodeType* top) { if(q == NULL || top == NULL) { return 0; } if(q->head == NULL) { return 0; } *top = q->head->data ; return 1; }
#include"LinkQueue.h" #include<stdio.h> void TEST_LinkQueue() { QueueNodeType tmp = 0; TEST_HEADER; LinkQueueInit(&q); LinkQueuePush(&q,'a'); LinkQueuePush(&q,'b'); LinkQueuePush(&q,'c'); LinkQueuePush(&q,'d'); LinkQueueTop(&q,&tmp); printf("expect is a,actual is %c\n",tmp); LinkQueuePop(&q); LinkQueueTop(&q,&tmp); printf("expect is b,actual is %c\n",tmp); LinkQueuePop(&q); LinkQueueTop(&q,&tmp); printf("expect is c,actual is %c\n",tmp); LinkQueuePop(&q); LinkQueueTop(&q,&tmp); printf("expect is d,actual is %c\n",tmp); LinkQueuePop(&q); } int main() { TEST_LinkQueue(); return 0; }