今天学历配对堆,然鹅我把普通的堆忘了,配对堆也听得云里雾里。。。现在自己来现场yy一下
手写堆
push就把元素放到最后面,不断把他和父亲比较,上浮
pop就把堆顶和最后一个元素交换,然后对交换后的堆顶不断和他的左右儿子比较(选左右儿子中优先级高的比),下沉,最大下沉到最后一个元素下标-1的位置,然后元素总数-1
代码:(大根堆)
#include<cstdio> #include<algorithm> using namespace std; #define lson(x) (x<<1) #define rson(x) ((x<<1)+1) #define fat(x) (x>>1) int tot=0,a[100010]; void swap(int &a,int &b){ if(&a==&b)return; a^=b^=a^=b; } void putdown(int x,int m){//下沉的点的下标&最大下沉下标 int l=lson(x),r=rson(x),tag; if(l>m)return; if(r<=m&&a[r]>a[l])tag=r; else tag=l; //找到左右儿子中最[大]的来替换 if(a[x]<a[tag])swap(a[x],a[tag]); putdown(tag,m);//继续下沉 } void putup(int x){ int fa=fat(x); if(fa<1)return; if(a[x]>a[fa])swap(a[x],a[fa]); putup(fa); } void push(int num){ a[++tot]=num; putup(tot); } void pop(){ swap(a[1],a[tot]); printf("你刚刚干掉了堆顶,他的值为%d ",a[tot]); --tot; putdown(1,tot); } //大根堆 int t; int main(){ scanf("%d",&t); printf("input “1”for push,or input “0” for pop。"); for(int i=1;i<=t;i++){ int ques; scanf("%d",&ques); if(ques){ int kkk; scanf("%d",&kkk); push(kkk); }else pop(); } return 0; }
堆排序
知道堆的运作原理,实现堆排序就很简单了,注意假如你是大根堆,要求从小到大排列,输出时要反过来(因为每次pop都把最大的搞到当前的最后)
下面是吧序列从大到小排:
#include<cstdio> #include<algorithm> using namespace std; #define lson(x) (x<<1) #define rson(x) ((x<<1)+1) int n,a[100010]; void swap(int &a,int &b){ a^=b^=a^=b; } void update(int x,int m){//下沉的点的下标&最大下沉下标 int l=lson(x),r=rson(x),tag; if(l>m)return; if(r<=m&&a[r]>a[l])tag=r; else tag=l; //找到左右儿子中最[大]的来替换 if(a[x]<a[tag])swap(a[x],a[tag]); update(tag,m);//继续下沉 } void heap_sort(){ for(int i=n;i>=1;i--)update(i,n);//建堆 for(int i=n-1;i>=1;i--){ swap(a[i+1],a[1]);//交换对顶和最后一个节点,相当于pop update(1,i);//注意这里最大下沉到i(防止堆顶不再浮上来) } } //大根堆 int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); heap_sort(); for(int i=n;i>=1;i--)//反着输出 printf("%d ",a[i]); return 0; }