隊列:只允許在一段進行插入,在另一端進行刪除的線性表。
循環隊列:具有隊頭指針和隊尾指針,指示隊列元素所在的位置,避免刪除元素時移動大量元素。
循環隊列特性:
- 只能隊尾插入元素、在隊頭刪除元素。
- 先進先出(First In First Out)的線性表,先進入的元素出隊,後進入的元素才能出隊。
優點:
- 相比普通的隊列,元素出隊時無需移動大量元素,只需移動頭指針。
- 適合處理用戶排隊等待的情況。
缺點:
- 需要預先分配大量存儲空間。
時間複雜度
- 讀取時的時間複雜度爲O(1)。
- 插入、刪除時的時間複雜度爲O(1)。
隊列示意圖
循環隊列插入元素示意圖
循環隊列刪除元素示意圖
// 隊列(循環隊列)
#include <stdio.h>#define OK 1 // 執行成功
#define ERROR 0 // 執行失敗
#define TRUE 1 // 返回值爲真
#define FALSE 0 // 返回值爲假
#define MAXSIZE 20 // 存儲空間初始分配大小typedef int Status; // 函數返回結果類型
typedef int ElemType; // 元素類型// 循環隊列的順序存儲結構
typedef struct {
ElemType data[MAXSIZE]; // 存儲隊列元素
int front; // 頭指針
int rear; // 尾指針
} SqQueue;/**
* 初始化隊列
* @param Q 隊列
* @return 執行狀態
*/
Status InitQueue(SqQueue *Q) {
Q->front = Q->rear = 0;
return OK;
}/**
* 清空隊列
* @param Q 隊列
* @return 執行狀態
*/
Status ClearQueue(SqQueue *Q) {
Q->front = Q->rear = 0;
return OK;
}/**
* 判斷隊列是否爲空
* @param Q 隊列
* @return 隊列是否爲空
*/
Status QueueEmpty(SqQueue Q) {
// 頭指針等於尾指針,隊列爲空
if (Q.front == Q.rear) {
return TRUE;
} else {
return FALSE;
}
}/**
* 獲取隊列長度
* @param Q 隊列
* @return 隊列長度
*/
int QueueLength(SqQueue Q) {
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}/**
* 獲取隊列頭元素
* @param Q 隊列
* @param e 存儲頭元素值
* @return 執行狀態
*/
Status GetHead(SqQueue Q, ElemType *e) {
// 隊列爲空,獲取失敗
if (Q.front == Q.rear) {
return ERROR;
}*e = Q.data[Q.front]; // 將隊列頭元素存儲到元素e中
return OK;
}/**
* 在隊列的隊尾處插入元素
* @param Q 隊列
* @param e 插入元素值
* @return 執行狀態
*/
Status EnQueue(SqQueue *Q, ElemType e) {
// 隊列滿時,插入失敗
if ((Q->rear + 1) % MAXSIZE == Q->front) {
return ERROR;
}Q->data[Q->rear] = e; // 在隊尾處插入元素e
// 隊尾指針向後移動,若到最後則轉向數組頭部
Q->rear = (Q->rear + 1) % MAXSIZE;
return OK;
}/**
* 刪除隊頭元素
* @param Q 隊列
* @param e 存儲出隊元素的值
* @return 執行狀態
*/
Status DeQueue(SqQueue *Q, ElemType *e) {
// 隊滿時,出隊失敗
if (Q->front == Q->rear) {
return ERROR;
}*e = Q->data[Q->front]; // 將隊列頭元素存儲到元素e中
// 隊頭指針向後移動,若到最後則轉向數組頭部
Q->front = (Q->front + 1) % MAXSIZE;
return OK;
}/**
* 打印單個元素
* @param e 元素值
* @return 執行狀態
*/
Status visit(ElemType e) {
printf("%d ", e);
return OK;
}/**
* 遍歷隊列中的元素
* @param Q 隊列
* @return 執行狀態
*/
Status QueueTravel(SqQueue Q) {
int i; // 用於遍歷元素的下標
i = Q.front; // 指向隊頭指針printf("[ ");
// 當指針不等於隊尾指針
while (i != Q.rear) {
visit(Q.data[i]); // 打印單個元素的值
i = (i + 1) % MAXSIZE; // 獲取下個元素的下標
}
printf("]\n");
return OK;
}int main() {
Status status; // 執行狀態
int i = 0, j;
ElemType e; // 元素值
SqQueue Q; // 隊列/*** 初始化隊列 ***/
InitQueue(&Q); // 初始化隊列
printf("初始化隊列後,隊列是否爲空?%s\n", QueueEmpty(Q) == TRUE ? "是" : "否");/*** 向隊列中插入10個元素 ***/
for (j = 1; j <=10; ++j) {
EnQueue(&Q, j); // 將元素j插入隊列
}
printf("插入10個元素後隊列的值爲:");
QueueTravel(Q); // 遍歷隊列
printf("隊列的長度爲:%d\n", QueueLength(Q)); // 獲取隊列長度
printf("插入10個元素後,隊列是否爲空?%s\n", QueueEmpty(Q) == TRUE ? "是" : "否");/*** 刪除隊列中的五個元素,並打印對應的值 ***/
printf("開始刪除元素:\n");
for (j = 0; j < 5; ++j) {
DeQueue(&Q, &e); // 刪除隊頭元素,將值存到e中
printf("元素%d出隊\n", e);
}
printf("5個元素出隊後,隊列中的值爲:");
QueueTravel(Q); // 遍歷隊列
printf("隊列的長度爲:%d\n", QueueLength(Q)); // 獲取隊列長度/*** 獲取隊列頭元素的值 ***/
status = GetHead(Q, &e); // 獲取隊列頭元素
if (status) {
printf("隊列頭元素爲:%d\n", e);
}/*** 清空隊列元素 ***/
ClearQueue(&Q); // 清空隊列元素
printf("清空隊列後,隊列是否爲空:%s\n", QueueEmpty(Q) == TRUE ? "是" : "否");
printf("隊列中的元素爲:");
QueueTravel(Q); // 遍歷元素
return 0;
}
運行結果
作者:lkmc2
鏈接:https://www.jianshu.com/p/962e0f3dd607
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。