數據結構(三) 隊列

版權聲明:轉載請附上文章地址https://blog.csdn.net/qq_42672839

1.隊列的概念 
只允許在一端插入數據操作,在另一端進行刪除數據操作的特殊線性表;進行插入操作的一端稱爲隊尾(入隊列),進行刪除操作的一端稱爲隊頭(出隊列);隊列具有先進先出(FIFO)的特性。

順序存儲就是用數組實現,比如有一個n個元素的隊列,數組下標0的一端是隊頭,入隊操作就是通過數組下標一個個順序追加,不需要移動元素,但是如果刪除隊頭元素,後面的元素就要往前移動,對應的時間複雜度就是O(n),性能自然不高。

2.隊列的API

jdk1.5中的阻塞隊列的操作如下:

add        增加一個元索                     如果隊列已滿,則拋出一個IIIegaISlabEepeplian異常
remove   移除並返回隊列頭部的元素    如果隊列爲空,則拋出一個NoSuchElementException異常
element  返回隊列頭部的元素             如果隊列爲空,則拋出一個NoSuchElementException異常
offer       添加一個元素並返回true       如果隊列已滿,則返回false
poll         移除並返問隊列頭部的元素    如果隊列爲空,則返回null
peek       返回隊列頭部的元素             如果隊列爲空,則返回null
put         添加一個元素                      如果隊列滿,則阻塞
take        移除並返回隊列頭部的元素     如果隊列爲空,則阻塞

 

3.隊列的邏輯

3.1 正常的一個順序隊列:

隊列的特性:先進先出,進入隊列從左邊進入,從右邊出隊列,所以A先進也是A先出

3.2 循環隊列

循環公式 tail=(tail+1)%array.Length;

什麼是循環隊列呢?就是有兩個指針,front指向隊頭,rear指向對尾元素的下一個位置,元素出隊時front往後移動,如果到了對尾則轉到頭部,同理入隊時rear後移,如果到了對尾則轉到頭部,這樣通過下標front出隊時,就不需要移動元素了。

隊列爲空時,front和rear相等,那隊列什麼時候判斷爲滿呢?按照循環操作rear依次後移,然後再從頭開始,也是出現rear和front相等時,隊列滿。這樣跟隊列空的情況就相同了,爲了區分這種情況,規定數組還有一個空閒單元時,就表示隊列已滿,因爲rear 可能在front後面,也可能循環到front前面,所以隊列滿的條件就變成了(rear+1)%maxsize = front ,同時隊列元素個數的計算就是(rear -front+maxsize)%maxsize。

隊列的鏈式表示和實現(簡稱爲「鏈隊列」)

隊列的鏈式存儲是在鏈表的基礎上,按照「先進先出」的原則操作數據元素。

例如,將隊列(A,B,C,D,E)依次入隊,然後再依次出隊。

代碼實現:(C語言)

#include <stdio.h>
#include <stdlib.h>

typedef struct QNode
{
    int data;
    struct QNode *next;
}QNode;

QNode *initQueue()
{
    QNode *queue = (QNode*)malloc(sizeof(QNode));
    queue->next = NULL;
    return queue;
}

QNode *enQueue(QNode *rear, int data)
{
    QNode *enElem = (QNode*)malloc(sizeof(QNode));
    enElem->data = data;
    enElem->next = NULL;
    //使用尾插法向鏈隊列中添加數據元素
    rear->next = enElem;
    rear = enElem;
    return rear;
}

void DeQueue(QNode *front, QNode *rear)
{
    if (front->next == NULL) 
   {
        printf("隊列爲空");
        return ;
    }
    QNode *p = front->next;
    printf("%s", p->data);
    front->next = p->next;
    if (rear == p) 
   {
        rear = front;
    }
    free(p);
}

int main() 
{
    QNode *queue, *front, *rear;
    queue = front = rear = initQueue();  //創建頭結點
    //向鏈隊列中添加結點,使用尾插法添加的同時,隊尾指針需要指向鏈表的最後一個元素
    rear = enQueue(rear, A);
    rear = enQueue(rear, B);
    rear = enQueue(rear, C);
    rear = enQueue(rear, D);
    rear = enQueue(rear, E);
    //入隊完成,所有數據元素開始出隊列
    DeQueue(front, rear);
    DeQueue(front, rear);
    DeQueue(front, rear);
    DeQueue(front, rear);
    DeQueue(front, rear);
    DeQueue(front, rear);
    
  return 0;
}

運行結果:

ABCDE隊列爲空