能夠利用根堆求解大小位置的數組中前i大或者前i小的元素,也能夠將其進行按大小排序。ios
原理與特色:利用徹底二叉樹的父子結點在線性表中的索引關係,較爲高效的利用空間去實現樹形結構,並達到相關要求。這裏以索引值 1 爲堆頂元素索引做爲展開。數組
爲了更好的去使用大小根堆,採用標誌參數:max_heap和min_heap來實現大小根堆的切換,更好的下降了代碼量,同時也能儘可能保持功能的完整與執行的高效。函數
(不完善的地方:應該改進存放容器方式,避免容器的再哈希產生沒必要要的時間開銷,能夠在構造對象的時候就肯定容器的大小)測試
1 #include<iostream> 2 #include<stdlib.h> 3 #include<vector> 4 #include<ctime> 5 #define Size long long 6 using namespace std; 7 template<typename P> 8 class heap{ 9 private: 10 Size heap_size;//容量限制 11 Size heap_count;//數據計數 12 vector<P> heap_elem;//堆容器 13 int maxmin_heap;//選擇大\小根堆 14 15 void Up_adjust(int now);//上浮調整 16 void Down_adjust(P &top, int now);//下沉調整 17 public: 18 enum{max_heap=1, min_heap=-1}; 19 heap(Size s, int m=max_heap)://構造堆 20 heap_size(s){ 21 heap_count=0; 22 heap_elem.push_back(-999); 23 maxmin_heap=m;//default max_heap 24 }; 25 P getTop(){//彈獲取堆頂元素 26 if(heap_count>0)return heap_elem[1]; 27 return heap_elem[0]*maxmin_heap; 28 } 29 bool empty(){//判斷堆空 30 if(heap_count==0)return true; 31 return false; 32 } 33 void push(P x);//送元素入堆 34 P pop();//堆頂元素彈出 35 void Delete(int i);//刪除第i個元素 36 void data();//打印堆 37 };
1.插入元素:將新元素放入堆底,執行上浮調整,使其合理this
1 template<typename P> 2 void heap<P>::push(P x){ 3 ++heap_count; 4 heap_elem.push_back(x*maxmin_heap); 5 int now=heap_count; 6 Up_adjust(now); 7 if(heap_count>heap_size-1) 8 heap_count--; 9 }
2.彈出元素:spa
template<typename P> P heap<P>::pop(){ this->Delete(0); return getTop()*maxmin_heap; }
3.刪除元素:code
用堆底元素替換,並經過下沉調整,使其合理對象
1 template<typename P> 2 void heap<P>::Delete(int i){ 3 if(i>heap_count) return; 4 cout << "delete heap["<< i <<"]: " << heap_elem[i]*maxmin_heap << endl; 5 if(i==heap_count){ 6 heap_count--; 7 return ;} 8 Down_adjust(heap_elem[heap_count],i); 9 heap_count--; 10 }
4.上浮調整:blog
1 template<typename P> 2 void heap<P>::Up_adjust(int now){ 3 while(now>1 && heap_elem[now]>heap_elem[now/2]){ 4 std::swap(heap_elem[now], heap_elem[now/2]); 5 now=now/2; 6 } 7 }
5.下沉調整:排序
1 template<typename P> 2 void heap<P>::Down_adjust(P &top, int now){ 3 heap_elem[now]=top; 4 int next1,next2; 5 while(now*2<=heap_count){ 6 if(now*2+1>heap_count){ 7 next1=next2=now*2; 8 } 9 else{ 10 next1 = heap_elem[now*2]>heap_elem[now*2+1] ? now*2 : now*2+1; 11 next2 = heap_elem[now*2]<heap_elem[now*2+1] ? now*2 : now*2+1; 12 } 13 if(heap_elem[next1]>heap_elem[now]){ 14 swap(heap_elem[next1],heap_elem[now]); 15 now = next1; 16 } 17 else if(heap_elem[next2]>heap_elem[now]){ 18 swap(heap_elem[next2],heap_elem[now]); 19 now = next2; 20 } 21 else{ 22 break; 23 } 24 } 25 }
6.數據打印:
1 template<typename P> 2 void heap<P>::data(){ 3 typename std::vector<P>::iterator itr=heap_elem.begin()+1; 4 cout << "heap[]: "; 5 for(int i=0;i<heap_count && i<heap_size;++i){ 6 cout << *(itr+i)*maxmin_heap << ' '; 7 } 8 cout << endl; 9 }
能夠註釋掉標準輸出語句,來減小執行操做的時間消耗,能更好測試大量數據插入、刪除的實行時間。
1 int main(){ 2 heap<int> h(20,heap<int>::min_heap); 3 int x; 4 srand(time(NULL)); 5 for(int i=0;i < 20;++i){ 6 x = rand()%1000; 7 h.push(x); 8 //h.data(); 9 } 10 h.data(); 11 h.Delete(4); 12 while(!h.empty()){ 13 h.pop(); 14 } 15 cout << endl; 16 return 0; 17 }