與棧不一樣,他就是現實中排隊同樣,講究先來後到,即 先進先出。
打個比方,你告訴朋友咱們作地鐵去西湖,你輸入 "s-u-b", 若是按照棧 先入後出後入先出 的方式,朋友會收到 b-u-s, what?有地鐵,咱們幹嗎作兩個小時的汽車??? 隊列就可讓朋友按你輸入的順序依次收到 s-u-b 。bash
簡單的看一下隊列,是線性結構,想到什麼?很是熟悉的 線性表 ,有兩種存儲結構,順序存儲和鏈式存儲。 咱們今天先講一講隊列的順序存儲結構——循環隊列markdown
可是,,,若是以下圖,出隊到只剩最後一個元素,front和rear又都指向了一個同元素,並且僅在隊尾,又要認爲隊列爲空?不可能啊,明明最後一塊存儲單元還有一個元素,並且卻不能繼續入隊新元素,超出了存儲範圍,若是要繼續利用前面出隊的空餘空間,又該怎麼用?函數
若是 咱們把隊列設計成下面這樣:測試
哈哈,循環了。隊尾rear指向下一個位置,而不是當前的隊尾元素。這就是循環隊列的工做流程spa
將上面的過程作一下整理:
設計
#define ERROR 0 #define TRUE 1 #define FALSE 0 #define OK 1 #define MAXSIZE 20 /* 存儲空間初始分配量 */ typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */ typedef int ElemType;/* ElemType類型根據實際狀況而定,這裏假設爲int */ /* 隊列結構 */ typedef struct { ElemType *data; int front; /* 記錄隊首元素位置 */ int rear; /* 記錄對尾元素位置 */ int max; /* 記錄開闢內存空間的大小 */ }SqQueue; 複製代碼
/// 初始化建立隊列 /// @param Q 隊列指針 /// @param n 指定開闢空間大小,一個空間大小是 sizeof(ElemType) Status InitQueue(SqQueue *Q, int n) { Q->data = malloc(sizeof(ElemType) * n); if (Q->data == NULL) return ERROR; Q->max = n; Q->front = Q->rear = 0; return OK; } 複製代碼
/// 獲取隊列元素個數(包括rear指向的空位置) /// @param Q 隊列 int GetLength(SqQueue Q) { return (Q.rear - Q.front + Q.max) % Q.max; } 複製代碼
Status QueueEmpty(SqQueue Q) { if (Q.front == Q.rear) { return OK; } return ERROR; } 複製代碼
Status QueueFull(SqQueue Q) { if ((Q.rear+1) % Q.max == Q.front) { return OK; } else { return ERROR; } } 複製代碼
Status GetFront(SqQueue Q, ElemType *e) { if (QueueEmpty(Q) == OK) { return ERROR; } *e = Q.data[Q.front]; return OK; } 複製代碼
/// 入隊操做 /// @param Q 隊列 /// @param e 新數據 Status EnQueue(SqQueue *Q, ElemType e) { // 判斷隊列有沒有滿 if (QueueFull(*Q)) return ERROR; Q->data[Q->rear] = e; // 隊尾向後移動,取模運算,超出隊尾,實現循環繼續從隊首開始 Q->rear = (Q->rear+1) % Q->max; return OK; } 複製代碼
/// 出隊列 /// @param Q 隊列 /// @param e 出的元素 Status DeQueue(SqQueue *Q, ElemType *e) { // 判斷對了是否是空 if (QueueEmpty(*Q) == OK) return ERROR; *e = Q->data[Q->front]; // 隊首位置向後移動一位 Q->front = (Q->front+1) % Q->max; return OK; } 複製代碼
Status QueuePrint(SqQueue *Q) { /* 從隊首開時輸出,直到對尾 */ int i = Q->front; while (i != Q->rear) { printf("%d ",Q->data[i]); i = (i+1) % Q->max; } printf("\n"); return ERROR; } 複製代碼
指定隊列最大存儲5個單元,方便觀看指針
int main(int argc, const char * argv[]) { SqQueue queue; InitQueue(&queue, 5); printf("插入數據:"); for (int i = 0; i < 30; i++) { EnQueue(&queue, i); } QueuePrint(&queue); int e ; printf("出隊:"); if (DeQueue(&queue, &e)) { QueuePrint(&queue); } if (DeQueue(&queue, &e)) { QueuePrint(&queue); } int frontE; if (GetFront(queue, &frontE)) { printf("隊頭:%d\n",frontE); } printf("插入數據:"); scanf("%d",&e); EnQueue(&queue, e); QueuePrint(&queue); printf("插入數據:"); scanf("%d",&e); EnQueue(&queue, e); QueuePrint(&queue); printf("插入數據:"); scanf("%d",&e); EnQueue(&queue, e); QueuePrint(&queue); printf("插入數據:"); scanf("%d",&e); EnQueue(&queue, e); QueuePrint(&queue); printf("開始清空隊列\n"); ClearQueue(&queue); QueuePrint(&queue); DestoryQueue(&queue); return 0; } 複製代碼