1.隊列的定義:
隊列(Queue)是一種基礎且重要的線性數據結構,遵循先進先出(FIFO)?? 原則,即最早入隊的元素最先出隊,與棧不同的是出隊列的順序是固定的。隊列具有以下特點:
- ?FIFO原則?:元素按插入順序處理,隊頭(Front)刪除,隊尾(Rear)插入。
- ?操作受限?:僅允許在兩端操作(隊尾入隊、隊頭出隊),中間元素不可直接訪問
- 順序隊列(數組實現)??
- ?優點?:內存連續,訪問高效。
- ?缺點?:易“假溢出”(數組未滿但指針越界),需通過循環隊列優化:
- 隊尾指針循環:rear = (rear + 1) % size
。
- 隊滿條件:(rear + 1) % size == front
(犧牲一個存儲單元)。
?鏈式隊列(鏈表實現)??
- ?優點?:動態擴容,無固定大小限制
2. 隊列的實現:
首先我們打開visual studio,我們需要準備以下界面:
2.1 queue.h
代碼
其中queue.h主要是存放函數的調用的頭文件,內容如下:
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
#define QDataType int struct QueueNode
{QDataType data;struct QueueNode* next;//定義 next指針//我們可以嘗試使用單鏈表來完成
};
typedef struct QueueNode QNode;struct queue
{QNode* phead;QNode* ptail;int size;//為什么需要通過結構體來封裝兩個指針//原本需要通過二級指針來完成增加和刪除
};
typedef struct queue queue;
//上述完成結構體基本建設//接下來完成以下接口:
//初始化和銷毀
void QueueInit(queue* pq);
void QueueDestroy(queue* pq);//后增和前刪
void QueuePush(queue* pq, QDataType x);
void QueuePop(queue* pq);//取出之前的數和取出后面的數
QDataType QueueFront(queue* pq);
QDataType QueueBack(queue* pq);//返回隊列中有效值個數
int QueueSize(queue* pq);//判空
bool QueueEmpty(queue* pq);
這一塊代碼是棧的頭文件,我們給出接口,接下來我們要嘗試在stack.c
里面實現這些代碼,即這些頭文件的接口具體如何實現
1.2 queue.c
代碼
#include"queue.h"void QueueInit(queue* pq)
{pq->phead = pq->ptail = NULL;pq->size = 0;
}void QueueDestroy(queue* pq)
{QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;free(pcur);pcur = next;}pq->phead = pq->ptail = NULL;
}void QueuePush(queue* pq, QDataType x)
{QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("malloc fail");return;}tmp->data = x;tmp->next = NULL;if (pq->phead == NULL){//如果沒有初始化pq->phead = tmp;pq->ptail = tmp;pq->size++;}else {pq->ptail->next = tmp;pq->ptail = tmp;pq->size++;}
}void QueuePop(queue* pq)
{assert(pq);QNode* Pop = pq->phead;pq->phead = pq->phead->next;free(Pop);pq->size--;
}QDataType QueueFront(queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->data;
}QDataType QueueBack(queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->data;
}int QueueSize(queue* pq)
{assert(pq);return pq->size;
}bool QueueEmpty(queue* pq)
{assert(pq);return pq->size == 0;
}
我們通過編寫依次完成了這些代碼的編寫。我們接下來測試這些代碼是否正常源代碼如下:
#include"queue.h"void test1(queue* pq)
{QueueInit(pq);QueuePush(pq,1);QueuePop(pq);QueuePush(pq, 1);QueuePush(pq, 2);QueuePush(pq, 3);printf("%d ", QueueBack(pq));printf("%d ", QueueFront(pq));printf("%d", QueueSize(pq));QueueDestroy(pq);
}int main()
{queue q1;test1(&q1);
}
嘗試利用代碼來調試看看我們完成的接口是否有問題:
目前來看是沒有問題的。
3 總結:
隊列以其嚴格的FIFO特性和高效的操作,成為管理有序任務的理想工具。理解其實現差異(循環隊列 vs 鏈式隊列)和應用場景(調度、緩沖、BFS等),能顯著提升系統設計能力。實際開發中需根據數據規模?(靜態/動態)、性能需求?(時間/空間復雜度)和并發環境選擇合適的實現方式