Java通過JDBC實現資料庫的連線
阿新 • • 發佈:2021-01-08
堆
堆的應用比較多,比如堆排序等等,下面就來介紹下堆
堆是一棵樹(完全二叉樹)的形式,其每個結點都有一個值,且每個結點的值都大於/小於等於其父結點的值
- 小根堆:每個結點的值都大於等於其父結點的值
- 大根堆:每個結點的值都小於等於其父結點的值
注意:堆的根結點存放的是最大值或者最小值,但其他結點的值的排序是未知的,這與二叉搜尋樹不同
堆的基本操作
-
插入一個數
在末尾插入新的元素,然後向上調整
-
求堆中的最小(大)值
返回堆頂元素
-
刪除最小值
用末尾的元素去覆蓋堆頂元素,然後再將堆頂元素向下調整
-
刪除任意一個元素
將任意一個元素覆蓋堆頂元素,然後再將堆頂元素向下或者向上調整
-
修改任意一個元素
直接賦值,再將該元素向上或者向下調整
const int N = 100010; int heap[N],l; void down(int x) { //用t來代表根結點和其左右兒子中的最小值的下標 int t = x; //如果左兒子存在且左兒子小於t,則t等於左兒子 if (x * 2 <= l && heap[x * 2] < heap[t]) { t = x * 2; } if (x * 2 + 1 <= l && heap[x * 2 + 1] < heap[t]) { t = x * 2 + 1; } //當根結點不是最小值的時候 if (x != t) { swap(heap[t],heap[x]); down(t); } } void up(int x) { //當該點有父結點且該點的值大於其父結點的值,則進行交換 while (x/2 > 0 && heap[x/2] > h[x]) { swap(heap[x/2],heap[x]); x /= 2; } } //最小值 heap[1]; //刪除最小元素 heap[1] = heap[l]; l--; down(1);
解釋:為何刪除元素時需要覆蓋堆頂元素,再調整
由於我們使用陣列儲存堆,在陣列中,刪除第一個元素比較困難,但刪除最後一個元素比較簡單,我們只需要用最後一個元素覆蓋掉第一個元素,這樣一來,最後一個元素還儲存在陣列中,只是位置變了,而要刪除的元素已經不在了,此時我們使陣列的長度減一,再將第一個元素進行排序,調整到合適的位置即可
堆的儲存方式
我們採用陣列的方式去實現堆
下標從1開始時:
- x的左兒子:2 * x
- x的右兒子:2 * x + 1
堆的建立
我們在陣列儲存了所有的元素後,需要建堆,此時我們一般採用一種O(n)的方法來實現
以小根堆為例,我們從n/2處的元素開始執行向下調整(down)操作
for (int i = n/2;i > 0; i--) {
down(i);
}
解釋:因為n/2是堆的倒數第二層,所以我們將上面的所有元素都進行一個下沉操作來維護堆的有序
STL中的堆
c++中,提供了一個優先佇列,實現堆的功能
priority_queue自動實現排序
//大根堆
priority_queue<int> heap;
//小根堆
priority_queue<int,vector<int>,greater<int>> heap;
//返回堆頂元素
heap.top();
//向堆插入一個數
heap.push(1);
//彈出堆頂元素
heap.pop();
//判斷堆是否為空
heap.empty();
//返回元素個數
heap.size();