算导挪着看终于看到了堆,大概是因为数构有过接触的原因,看它也比较亲切,算是入门了。
挺喜欢堆的,大约是因为它可爱?(像树?)
挪数也是挪的辛苦,堆也是很任性的呀。
一 堆
堆,在我的理解里就是把数组里的数排成完全二叉树的样子,比如:
堆的样子其实是虚拟的,只是为了更好的看清楚一堆数字是怎么移动的。
这样的好处有很多啦,
r=2*i && l=2*i+1
这样左右子树就好算啦(递归),而且算父节点也方便。
二 堆的性质
堆嘛,喜欢的可以排成最大堆或者最小堆(叫大根堆,小根堆会不会萌一点?)
大根堆的特性:
小根堆的特性:(太丑了不画了233333,orz,受不了我自己)
也就是父节点必须要大于或者小于子节点啦!
那么对于一堆无序的随机数,就要做一定的处理--max_heapify:
1) A[i]&A[left(i)]&A[right(i)]中找最大值,并且将其下标保存在largest中。
2) if A[i] is largest , then it is over
3) else exchange A[i]<->A[largest]
in order to make these numbers keep the rule.
4) (神奇的)递归来了。
再一次: max_heapify(A,largest)
三 建堆
建堆其实就是将一个数组中的所有元素一个个插入排好,每插入一个元素,就要调用一次max_heapify
四 堆的排序算法
大boss~来了。
我深深的觉得这是一个很神奇而且很粗暴的排序算法...
就是通过把数都排成最大堆,然后将根结点取出来(相当于毁掉),然后对剩下的数做相同的事...(残暴吧,也就是说,排完序之后,这个堆算是毁掉了)
图图:
begin:
again & agian...
finally:
当!数组出来了!
最后的数组输出可以在程序中取的时候直接输出,也可以用一个数组保存起来,最后输出(感觉这个比较麻烦啦)
1 # include <iostream> 2 # include <vector> 3 4 using namespace std; 5 6 void max_heapify(vector<int>&a,int i) 7 { 8 9 int left; int right; int largest; 10 left = (i+1)*2-1; 11 right = (i+1)*2; 12 13 if(left<a.size()) 14 max_heapify(a,left); 15 if(right<a.size()) 16 max_heapify(a,right); 17 18 if(left<a.size()&&a[left]>a[i]) 19 largest=left; 20 else 21 largest=i; 22 if(right<a.size()&&a[right]>a[largest]) 23 largest=right; 24 if(largest!=i) 25 { 26 int temp; 27 temp=a[i]; 28 a[i]=a[largest]; 29 a[largest]=temp; 30 } 31 32 } 33 34 void initial(vector<int>&a,int n) 35 { 36 for(int i=0; i<n; i++) 37 { 38 int m; 39 cin >> m ; 40 a.push_back(m); 41 } 42 cout<<endl; 43 int j; j=0; 44 for(int i=0; i<n/2; i++) 45 max_heapify(a,j); 46 47 } 48 49 void heapsort(vector<int>&a,int n) 50 { 51 initial(a,n); 52 for(int i=n-1; i>=0; i--) 53 { 54 cout << a[0] << " "; 55 int temp; 56 temp=a[0]; 57 a[0]=a[i]; 58 a[i]=temp; 59 if(i==0) continue; 60 a.pop_back(); 61 max_heapify(a,0); 62 } 63 64 } 65 66 int main() 67 { 68 int n; 69 cout << "n: " << endl; 70 cin >> n; 71 vector<int>data; 72 heapsort(data,n); 73 74 return 0; 75 }