數據結構(10)隊列之順序隊列
前言
在隊列的順序存儲結構中,除了用一組地址連續的存儲單元來存放元素之外,一般還會附設兩個指針fount和rear來指示隊頭和隊尾元素的位置,這樣更有隊列的特點,但是它本質上仍是順序表。
順序隊列的初始化與插入刪除
通常約定,初始化空隊列時,讓fount和rear初始化爲0,每當需要插入元素(即新元素入隊)時,尾指針(rear)加一;要刪除元素(即隊首出隊)時,頭指針(fount)加一。這樣,在非空順序隊列裏,頭指針始終指向隊頭元素,尾指針則指向隊尾元素的下一個位置。
遍歷時,從fount指示的隊首位置開始,到rear指示的前一個位置結束。
順序隊列所存在的問題
在順序隊列中,當我們要執行插入操作時,首先需要判斷隊列是否已滿,如果隊列已滿是無法插入元素的;而判斷是否已滿的條件是看rear指針是否大於等於隊列最大容量。當然,在以往的順序表中,也可以重新去申請內存來實現插入的需求。但是先看看到我們的刪除操作,只是將fount指針自增,不進行其他操作。這樣就會造成一個現象:隊列邏輯上已經滿了(rear的指向已經越界了),實際上仍是有空間的(隊首元素之前的空間還可用)。
我們稱這種現象爲“假溢出”。顯然,在假溢出的情況下去重新申請內存是不合適的,合理的考慮是先充分利用之前的空間,這樣就出現了一種比較特殊的結構——循環隊列,會在下篇博客中詳細說明。
也有人會覺得:假如讓fount指針固定爲0,要出隊時將隊首元素後的所有元素向前移不就行了嗎?這樣的確可以解決假溢出的問題,但是每次出隊都要移動大量元素,性能就降低了。這也是順序隊列大多都設置爲循環隊列的原因——既解決問題,又保證了性能。
全部代碼
SeqQueue.h
#ifndef SeqQueue_h
#define SeqQueue_h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define ElemType int
#define MAXSIZE 8
typedef struct Queue{
ElemType *base;
int fount;
int rear;
}Queue;
//初始化
void InitQueue(Queue *Q);
//入隊
void EnQueue(Queue *Q,ElemType x);
//出隊
void DeQueue(Queue *Q);
//展示
void ShowQueue(Queue *Q);
//獲取隊首元素
void GetHead(Queue *Q,ElemType *x);
//求長度
int GetLength(Queue *Q);
//清除
void CleatQueue(Queue *Q);
//摧毀
void DestoryQueue(Queue *Q);
#endif /* SeqQueue_h */
SeqQueue.c
#include "SeqQueue.h"
//初始化
void InitQueue(Queue *Q){
//開闢空間
Q->base = (ElemType *)malloc(sizeof(ElemType)*MAXSIZE);
assert(Q->base != NULL);
//隊頭指針和隊尾指針指向0下標
Q->fount = Q->rear = 0;
}
//入隊
void EnQueue(Queue *Q,ElemType x){
//判斷隊列是否滿
if (Q->rear >= MAXSIZE) {
//滿了
printf("隊列已滿\n");
return;
}
Q->base[Q->rear++] = x;
}
//出隊
void DeQueue(Queue *Q){
//判斷隊列是否空
if (Q->fount == Q->rear) {
printf("隊列已空\n");
return;
}
Q->fount++;
}
//展示
void ShowQueue(Queue *Q){
for (int i = Q->fount; i < Q->rear; i ++) {
printf("%4d",Q->base[i]);
}
printf("\n");
}
//獲取隊首元素
void GetHead(Queue *Q,ElemType *x){
//判斷隊列是否空
if (Q->fount == Q->rear) {
printf("隊列已空\n");
return;
}
*x = Q->base[Q->fount];
}
//求長度
int GetLength(Queue *Q){
return (Q->rear - Q->fount);
}
//清除
void CleatQueue(Queue *Q){
Q->fount = Q->rear = 0;
}
//摧毀
void DestoryQueue(Queue *Q){
free(Q);
Q->base = NULL;
}
Main.c
#include "SeqQueue.h"
int main(int argc, const char * argv[]) {
Queue Q;
InitQueue(&Q);
//入隊
for (int i = 0; i < 5; i ++) {
EnQueue(&Q, i);
}
ShowQueue(&Q);
//出隊
DeQueue(&Q);
ShowQueue(&Q);
return 0;
}