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...