堆排序回顾
这东西。。。好简单的诶
不过貌似一年前的时候,还没有写博客的习惯
那就来总结一下呗
堆排序的好处是他一定不会退化,而快排会退化
首先来说大根堆
把大根堆当成一个完全二叉树(这个说法其实不准确)
对于a[i],左儿子为a[i*2]右儿子为a[i*2+1]
也就是说我们已经有一颗树了
然后我们从后往前fix每个节点
fix(x)就是将x放到他该在的地方
具体操作就是,将x与其两个子节点比较
如果x>他的两个节点,退出函数
如果x<他的两个节点
将x与他的两个节点中的最大的节点y调换位置,然后fix(y)
如果他的某个子节点为空,那就设这个子节点的值为-inf
在建好堆后,我们就可以保证堆顶元素最大了嘛
于是我们把堆顶元素放入数组,然后把堆尾元素放到堆顶,最后再fix(1)
重复这个过程直到堆中元素为0
代码:
这代码我一年前写的,写的好丑,请不要介意
#include <iostream> using namespace std; int parent(int i){return i/2;} int left (int i) {return i*2;} int right (int i) {return i*2+1;} void maintenance (int *a,int i,int len); void Swap(int &a,int &b) {int s;s=a;a=b;b=s;return;} void in(int *a,int &l); void build(int *a,int l); void heap_sort(int *a,int l); int main() { int a[5000],l; in(a,l); build(a,l); heap_sort(a,l); for (int k=1;k<=l;k++) cout<<a[k]<<" "; return 0; } void in (int *a,int &l) { int i=1; while (cin>>a[i]) i++; l=i-1; return; } void maintenance (int *a,int i,int len) { int l=left(i),r=right(i),large=0; if (l<=len&&a[i]<a[l]) large=l; else large=i; if (r<=len&&a[large]<a[r]) large=r; if (large==i) return; Swap(a[i],a[large]); maintenance(a,large,len); return; } void build (int *a,int l) { for (int k=l/2;k>=1;k--) maintenance(a,k,l); return; } void heap_sort(int *a,int l) { for (int k=l;k>=1;k--) { Swap(a[1],a[k]); l--; maintenance(a,1,l); } return; }