數據結構中的隊列有“先進先出”的特點,意思是最先被存進隊列中的數據,總是最先被取走
一個隊列只有初始化,銷燬,入隊列,出隊列和取隊首元素,這些限制往往使在操作數據時更安全,代碼容易實現,出現BUG的機會就很少
上圖隊列,如過進行了多次入隊列和出隊列,就會是head之前的空間浪費,如下圖
爲了避免這種浪費空間的測操作,當每次head 和 tail 只要到達最後一個元素,操作完成就讓他們回到對列的最前面,即head = 0 或 tail = 0,這樣head == taill 時,可能是空對列,也可能是滿對列,所以判斷對列是否滿了出現困難,在對列的機構體中加上一個size成員,用來判斷是否對列已滿
頭文件(SeqQueue.h)
#pragma once
typedef char QueueType;
typedef struct SeqQueue{
QueueType* place; //隊列的空間
size_t head; //隊首標記
size_t tail; //隊尾標記
size_t size; //對列當前存儲元素的個數
size_t max_size; //對列最大存儲元素個數
}SeqQueue;
void SeqQueueInit(SeqQueue* queue); //隊列初始化
void DestroyQueue(SeqQueue* queue); //銷燬隊列
void SeqQueueIn(SeqQueue* queue, QueueType value); //入隊列
void SeqQueueOut(SeqQueue* queue); //出隊列
int SeqQueueFront(SeqQueue* queue, QueueType* output_value); //取隊首元素
頭文件的實現(SeqQueue.c)
#include<stdio.h>
#include<stdlib.h>
#include"SeqQueue.h"
void SeqQueueInit(SeqQueue* queue) {
queue->max_size = 1;
queue->size = 0;
queue->head = 0;
queue->tail = 0;
queue->place = malloc(queue->max_size * sizeof(SeqQueue));
if(queue->place == NULL) {
printf("malloc 失敗!\n");
exit(1);
}
}
void DestroyQueue(SeqQueue* queue) {
if(queue == NULL) {
return;
}
free(queue->place);
queue->place = NULL;
queue->max_size = 0;
queue->size = 0;
queue->head = 0;
queue->tail = 0;
}
void SeqQueueIn(SeqQueue* queue, QueueType value) {
if(queue == NULL) {
return;
}
if(queue->size >= queue->max_size) {
queue->max_size = 2 * queue->max_size + 1;
QueueType* new_place = malloc(queue->max_size * sizeof(SeqQueue));
int i = 0;
if(queue->tail == queue->head) {
for(i = 0; i < queue->tail; i++) {
new_place[i] = queue->place[i];
}
queue->tail = i;
for(i = 1; i <= (queue->size - queue->head); i++) {
new_place[queue->max_size - i] = queue->place[queue->size - i];
}
queue->head = queue->max_size - i;
}
else if(queue->tail > queue->head) {
for(i = 0; i < queue->size; i++) {
new_place[i] = queue->place[i];
}
}
free(queue->place);
queue->place = new_place;
}
if(queue->tail == queue->max_size) {
queue->tail = 0;
}
if(queue->head == queue->max_size) {
queue->head = 0;
}
queue->place[queue->tail] = value; queue->tail++; queue->size++;}void SeqQueueOut(SeqQueue* queue) { if(queue == NULL) { return; } if(queue->size == 0) { return; } if(queue->head == queue->max_size) { queue->head = 0; } queue->head++; queue->size--;}int SeqQueueFront(SeqQueue* queue, QueueType* output_value) { if(queue == NULL || output_value == NULL) { *output_value = 0; return 0; } if(queue->size == 0) { *output_value = 0; return 0; } *output_value = queue->place[queue->head]; return 1;}/////////////////////////////////////////////////////以下爲測試代碼///////////////////////////////////////////////////void TestQueue() { SeqQueue queue; SeqQueueInit(&queue); SeqQueueIn(&queue, 'a'); SeqQueueIn(&queue, 'b'); SeqQueueIn(&queue, 'c'); SeqQueueIn(&queue, 'd'); int ret; QueueType value; ret = SeqQueueFront(&queue, &value); printf("expected a, actrual %c\n", value); printf("expected 1, actrual %d\n", ret); SeqQueueOut(&queue); ret = SeqQueueFront(&queue, &value); printf("expected b, actrual %c\n", value); printf("expected 1, actrual %d\n", ret); SeqQueueOut(&queue); ret = SeqQueueFront(&queue, &value); printf("expected c, actrual %c\n", value); printf("expected 1, actrual %d\n", ret); SeqQueueOut(&queue); ret = SeqQueueFront(&queue, &value); printf("expected d, actrual %c\n", value); printf("expected 1, actrual %d\n", ret); SeqQueueOut(&queue); ret = SeqQueueFront(&queue, &value); printf("expected 0, actrual %d\n", value); printf("expected 0, actrual %d\n", ret); SeqQueueOut(&queue);}int main(){ TestQueue(); return 0;}
實驗結果
補充:隊列滿了的情況有兩種
第一種:
只需要從舊的空間把head和tail之間的數據對應複製到新的空間
第二種:
把舊0-tail的數據複製到新空間的0-tail
把head到最後一個數據 之間的數據按順序複製到新空間的最後面