堆(優先順序佇列)

2021-07-16 07:52:04 字數 3789 閱讀 2199

c++ 的 stl 中提供了「優先佇列」這一容器,它和普通的 fifo 佇列都定義在 中,有 push() 和 pop() 過程,分別表示「往佇列裡加入新元素」和「從佇列裡刪除隊首元素」

唯一的區別是,在優先佇列中,元素並不是按照進入佇列的先後順序排列,而是按照優先順序的高低順序排列

換句話說,pop() 刪除的是優先順序最高的元素,而不一定是最先進入佇列的元素。正因為如此,獲取隊首元素的方法不再是 front(),而是 top()

定義優先佇列最簡單的方法是 priority_queue《型別名》 q,它利用元素自身的「小於」操作符來定義優先順序

例如,在 priority_queueq 這樣的優先佇列中,先出隊的總是最大的整數

1、過載「

如果優先佇列的元素型別是結構體,可以通過在結構體中過載「

struct node 

};

2、過載「()」操作符來定義優先順序

如果優先佇列的元素不是結構體型別,則可以通過過載「()」操作符的方式來定義優先順序

當然,元素是結構體型別,也可以通過過載「()」操作符的方式來定義優先順序,而不是一定要在結構體內過載「

//「個位數大的優先順序反而小」的整數優先佇列

struct cmp

};priority_queue, cmp> q;

參考:

堆就是像下圖這樣的二叉樹

堆通常是乙個可以被看做一棵樹的陣列物件

堆總是滿足下列性質:

除此之外,樹的節點是按從上到下、從左到右的順序緊湊排列的

1、大頂堆與小頂堆

由堆序性不難看出,堆中優先順序最高的詞條必然始終處於堆頂位置。因此,堆結構的獲得優先順序最高的詞條的操作總是可以在 o(1) 時間內完成

堆序性也可對稱地約定為「堆頂以外的每個節點都不低(小)於其父節點」,此時同理,優先順序最低的詞條,必然始終位於堆頂位置

為以示區別,通常稱前(後)者為大(小)頂堆

小頂堆和大頂堆是相對的,而且可以相互轉換

2、堆的儲存

儘管二叉樹不屬於線性結構,但作為其特例的完全二叉樹,卻與向量有著密切的對應關係

所以我們一般用一維陣列來儲存堆,按照層次遍歷序列,對完全二叉樹節點做編號,這樣我們就可以將堆定義為滿足某種關係的 n 個元素的序列

那麼第 1 個元素儲存的就是堆頂的元素,每個節點的左右子節點分別為第 i*2 和 i*2+1 個元素,堆頂以外的每個節點的父節點為第 i/2 個元素

3、堆的插入

void insert(int key)

}

4、堆的刪除

按定義,堆中每次都只能刪除堆頂元素

void delete(void)

if (num[pos] < num[pos>>1]) else }}

5、堆化陣列

對於序列 ,我們要如何對其進行堆化操作

很明顯,對每個葉子節點來說,它已經是乙個合法的堆了

我們只要從第 5 個元素 50 開始調整,然後再取 60, 17, 12, 9 分別進行調整,如圖所示

}6、堆排序

我們先建好乙個大頂堆,規定數值越大的元素的優先順序越高,那麼堆頂元素必然為最大的元素

將堆頂元素與第 n 個元素交換,然後再對第 1 個元素到第 n-1 個元素進行調整,重新恢復為堆,重複這樣的操作直到交換堆頂元素和第 2 個元素

這就是乙個堆排序的過程

由於每次都將當前區間最大的整數放到後面的有序區間,故整個操作完成後陣列就是乙個從小到大排列的有序序列了

時間複雜度:o(n * logn)

void heap_sort(void)

if (num[j] <= num[j>>1])

swap(num[j], num[j>>1]);

j <<= 1;}}

}void build_heap(void)

if (num[j] > num[j>>1]) else }}

}

參考:

1、make_heap

stl 預設建立的是最大堆,對int型別,可以在第三個引數傳入greater() 得到最小堆

2、push_heap

需要先在末尾加入資料,再進行呼叫

3、pop_heap

呼叫後需要刪除末尾資料

4、sort_heap

排序以後就不是乙個合法的堆了

#include #include #include #include #include #include #include #include #include #include #include using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef unsigned int uint;

const ull mod = 1e9 + 7;

const int inf = 0x7fffffff;

const int maxn = 1e5 + 10;

int num[maxn];

int n;

int main()

vectorv(num, num+n);

make_heap(v.begin(), v.end());

printf("initial max heap : %d\n", v[0]);

pop_heap(v.begin(), v.end());

v.pop_back();

printf("max heap after pop : %d\n", v[0]);

v.push_back(99);

push_heap(v.begin(), v.end());

printf("max heap after push: %d\n", v[0]);

sort_heap(v.begin(), v.end());

printf("final sorted range :");

for (int i = 0; i < n; ++i)

printf("\n");

return 0;}/*

input :

91 4 7 2 5 8 3 6 9

output :

initial max heap : 9

max heap after pop : 8

max heap after push: 99

final sorted range :1 2 3 4 5 6 7 8 99

*/

參考:

1、d 叉堆

堆 優先順序佇列

1一般二叉樹的順序儲存 層序遍歷方式 使用陣列儲存二叉樹結構,即將二叉樹 按照層序遍歷 的方式放入陣列.這種方式一般只適用於完全二叉樹,一般的二叉樹會造成空間浪費比較嚴重.2堆 heap 在邏輯上就是乙個 完全二叉樹,在物理上儲存在 陣列 中.1 滿足任意結點的值都大於其子樹的結點的值.叫做大堆,反...

優先順序佇列 堆

1.1 堆的概念 堆邏輯上是一棵完全二叉樹 堆物理上是儲存在陣列中位元科技 滿足任意結點的值都大於其子樹中結點的值,叫做大堆,或者大根堆,或者最大堆 反之,則是小堆,或者小根堆,或者最小堆 堆的基本作用是,快速找集合中的最值 1.2儲存方式 使用陣列儲存二叉樹結構,方式是將二叉樹用層序遍歷方式放入陣...

優先順序佇列(堆)

2 堆 heap 3 優先順序佇列 使用陣列儲存二叉樹結構,方式即將二叉樹用層序遍歷方式放入陣列中。一般只適合表示完全二叉樹,因為非完全二叉樹會有空間的浪費。這種方式的主要用法就是堆的表示。已知雙親 parent 的下標,則 左孩子 left 下標 2 parent 1 右孩子 right 下標 2...