堆操作与堆排序
首先,我們來認(rèn)識堆:
?
堆的建立:將給定的序列按層次遍歷建立完全二叉樹,然后從最后一個非終端結(jié)點(diǎn)開始自下向上逐步調(diào)整為堆。
?
這里就有兩個重要的操作,shift_up(int t)和shift_down(int t),這樣我們就建立了堆。
對于堆排序,就相當(dāng)于每次取出堆頂?shù)脑刂?#xff0c;這樣是從大到小排序的,因?yàn)榻⒌氖谴箜敹选6雅判蚴且环N樹型
選擇排序。
?
現(xiàn)在來詳細(xì)說一點(diǎn):比如對于序列:5 8 9 7 6 4
按照層次遍歷建立完全二叉樹得到:
?
?
然后自底向上調(diào)整為大頂堆。
?
?
對于插入操作,是在原來堆的后面加上被插入的元素,然后自下而上調(diào)整堆,每次操作復(fù)雜度為O(log(n))。
對于刪除操作,就是把位于堆最后的那個元素覆蓋到被刪除元素的位置,然后調(diào)整堆,堆的size--。
?
而對于堆排序,就是每次刪除堆頂元素,把每次刪除的元素值保存在S[]里,刪除完畢后得到序列是一個有序序列,
也就是完成了排序,這樣可以知道堆排序的時間復(fù)雜度為O(nlog(n))。
?
#include <iostream> #include <string.h> #include <stdio.h>using namespace std; const int N = 105;int Heap[N]; int size;void shift_up(int t) {bool done = 0;if(t == 0) return;while(t != 0 && !done){if(Heap[t] > Heap[(t-1)/2])swap(Heap[t],Heap[(t-1)/2]);elsedone = 1;t = (t-1)/2;} }void shift_down(int t) {bool done = 0;if(2*t+1 > size) return;while(2*t+1 < size && !done){t = 2 * t + 1;if(t+1 < size && Heap[t+1] > Heap[t]) t++;if(Heap[(t-1)/2] < Heap[t])swap(Heap[(t-1)/2],Heap[t]);elsedone = 1;} }void Insert(int x) {if(size >= N) return;size++;Heap[size-1] = x;shift_up(size-1); }void Delete(int t) {int last = Heap[size-1];size--;if(t == size) return;Heap[t] = last;shift_down(t); }int Delete_maxval() {int tmp = Heap[0];Delete(0);return tmp; }int main() {int n;while(cin>>n){size = 0;for(int i=0;i<n;i++){int val;scanf("%d",&val);Insert(val);}while(size > 0)cout<<Delete_maxval()<<" ";cout<<endl;}return 0; }
?
總結(jié)
- 上一篇: 正方形个数(二维点哈希)
- 下一篇: 字符串的距离