優先隊列的基本算法(使用二叉堆構建優先隊列)

1、介紹ios

堆,也是計算中一種很經常使用的數據結構,它以樹的形式存在。 對於樹的結構,由於有父節點和子節點的概念,因此通常經過父指針和子指針來實現。可是,也有一種特殊的樹不須要使用指針而能夠直接經過數組來實現,這種樹就是徹底二叉樹(除了最後一層不用全滿,其餘層必須全滿,並且最後一層的葉子結點都靠左對齊)。今天咱們要討論的二叉堆就是一棵徹底二叉樹,二叉堆也是堆的一種,只不過二叉堆擁有本身的特色,它分爲最大堆和最小堆。算法

 

二叉堆特色:數組

最大堆:全部的父節點值都不小於其孩子節點值。(注意「其」字,僅限於當前父節點和它的子節點的比較)數據結構

最小堆:全部的父節點值都不大於其孩子節點值。(注意「其」字,僅限於當前父節點和它的子節點的比較)測試

算法: parent = floor(i/2),leftChild = 2*i,  rightChild = 2*i+1   [注意: 存儲的角標從1開始]。ui

 

二叉堆圖示:spa

  

 

2、使用debug

以前的篇幅介紹過鏈隊列和順序隊列,它們都是普通的隊列,採用先進先出的方式來對元素進行操做。但是,有的時候需求並非僅僅如此,可能會來一個優先級更高的元素操做,這個時候把它按照普通隊列的方式進行處理明顯是不合適的。並且,普通隊列的入隊和出隊的時間複雜度也不是最優的。此時採用二叉堆構建優先隊列,是一個折中的選擇,時間複雜度是最優的,如圖所示:3d

 

 

3、代碼指針

定義

#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <algorithm>

using namespace std;

#define QUEUE_OVERFLOW  -1
#define OK               1
#define ERROR            0

typedef int Status;
typedef int QElemType;

typedef struct BinaryHeap {
    int capacity;      //容量
    int count;         //個數
    QElemType *array;  //數組

}BinaryHeapQueue;

//構建二叉堆優先隊列
Status constructBinaryHeapQueue(BinaryHeapQueue &bq, int capacity);

//將元素添加到隊列
Status enQueueByShiftUp(BinaryHeapQueue &bq, QElemType e);

//從隊列中取出元素
Status deQueueByShiftDown(BinaryHeapQueue &bqt);

//獲取隊列元素個數
QElemType eleCount(BinaryHeapQueue &bq);

//判斷隊列是否爲空
Status isEmpty(BinaryHeapQueue &bq);

//判斷隊列是否已滿
Status isFull(BinaryHeapQueue &bq);

實現

//構建一個二叉堆
Status constructBinaryHeapQueue(BinaryHeapQueue &bq, int capacity) {

    assert(capacity > 0);

    //數組元素從下標1的位置開始存儲,因此多分配一塊內存
    bq.array = (QElemType *)malloc((capacity + 1) * sizeof(QElemType));
    bq.capacity = capacity+1;
    bq.count = 0;

    if (!bq.array) exit(QUEUE_OVERFLOW); //存儲分配失敗

    return OK;
}

//將元素e添加隊列
Status enQueueByShiftUp(BinaryHeapQueue &bq, QElemType e) {

    if (isFull(bq)){
        cout<<"隊列已滿,當前元素: "<<e<<" 沒法被添加到隊列"<<endl;
        return ERROR;
    }

    //保存元素
    bq.array[bq.count+1] = e;
    cout<<"入隊列元素: "<<"array["<<bq.count+1<<"] = "<<e<<endl;

    //若是這個入隊元素的值是比父節點值大,則往上移動
    int chiIndex = bq.count + 1;
    int parIndex = floor(chiIndex/2);
    while (bq.array[parIndex] < bq.array[chiIndex] && parIndex > 0) {
        swap(bq.array[parIndex], bq.array[chiIndex]);
    
     //從新賦值下標,進入循環 chiIndex
= parIndex; parIndex = floor(chiIndex / 2); } //個數自增 bq.count ++; return OK; } //從隊列中取出隊首元素保存到e中 Status deQueueByShiftDown(BinaryHeapQueue &bq) { if (isEmpty(bq)){ cout<<"隊列已空"<<endl; return ERROR; } //取出元素,並將尾部元素放到下標1的位置 QElemType e = bq.array[1]; bq.array[1] = bq.array[bq.count]; cout<<"出隊列元素: "<<"array[1] = "<<e<<endl; //個數自減 bq.count --; //若是當前下標1位置父節點的值是比孩子節點小,則往下移動 int parIndex = 1; int l_chiIndex = parIndex * 2; int r_chiIndex = parIndex * 2 + 1; while (r_chiIndex <= bq.count && bq.count > 1){ if (bq.array[parIndex] <= bq.array[l_chiIndex] || bq.array[parIndex] <= bq.array[r_chiIndex]) { //左孩子比右孩子值大,父節點和左孩子交換 if (bq.array[l_chiIndex] > bq.array[r_chiIndex]) { swap(bq.array[parIndex],bq.array[l_chiIndex]); parIndex = l_chiIndex; } else { swap(bq.array[parIndex],bq.array[r_chiIndex]); parIndex = r_chiIndex; }        //從新賦值下標,進入循環  l_chiIndex = parIndex * 2; r_chiIndex = parIndex * 2 + 1; } } return OK; } //獲取隊列元素個數 QElemType eleCount(BinaryHeapQueue &bq) { QElemType count = bq.count; cout<<"隊列元素個數: count = "<<count<<endl; return count; } //判斷隊列是否爲空 Status isEmpty(BinaryHeapQueue &bq) { return bq.count == 0; } //判斷隊列是否已滿 Status isFull(BinaryHeapQueue &bq) { return bq.count == bq.capacity-1; }

 

4、結果

測試

int main() {

    ///建立二叉堆優先隊列(本代碼以最大堆爲例) ------ 最小堆實現邏輯與其相似
    BinaryHeapQueue heapQueue;
    constructBinaryHeapQueue(heapQueue, 5);

    ///添加元素到隊列
    enQueueByShiftUp(heapQueue, 60);
    enQueueByShiftUp(heapQueue, 23);
    enQueueByShiftUp(heapQueue, 40);
    enQueueByShiftUp(heapQueue, 60);
    enQueueByShiftUp(heapQueue, 80);

    ///獲取元素的個數
    eleCount(heapQueue);

    ///先取出一個元素,再入隊兩個元素
    cout<<endl;
    deQueueByShiftDown(heapQueue);
    enQueueByShiftUp(heapQueue, 100);
    enQueueByShiftUp(heapQueue, 200);

    ///獲取元素的個數
    eleCount(heapQueue);
    cout<<endl;

    ///取出元素從隊列
    deQueueByShiftDown(heapQueue);
    deQueueByShiftDown(heapQueue);
    deQueueByShiftDown(heapQueue);
    deQueueByShiftDown(heapQueue);
    deQueueByShiftDown(heapQueue);
    deQueueByShiftDown(heapQueue);

    ///獲取元素的個數
    eleCount(heapQueue);

    return 0;
}

打印

/Users/xiayuanquan/CLionProjects/treeHeap/cmake-build-debug/treeHeap
入隊列元素: array[1] = 60
入隊列元素: array[2] = 23
入隊列元素: array[3] = 40
入隊列元素: array[4] = 60
入隊列元素: array[5] = 80
隊列元素個數: count = 5

出隊列元素: array[1] = 80
入隊列元素: array[5] = 100
隊列已滿,當前元素: 200 沒法被添加到隊列
隊列元素個數: count = 5

出隊列元素: array[1] = 100
出隊列元素: array[1] = 60
出隊列元素: array[1] = 60
出隊列元素: array[1] = 40
出隊列元素: array[1] = 23
隊列已空
隊列元素個數: count = 0

進程已結束,退出代碼 0
相關文章
相關標籤/搜索