• [OI学习笔记]堆&堆排序


    今天学历配对堆,然鹅我把普通的堆忘了,配对堆也听得云里雾里。。。现在自己来现场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;
    } 
    本篇文章为SHINE_GEEK原创,转载请注明来源!
    written_by:SHINE_GEEK

    -------------------------------------
    签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
    -------------------------------------
  • 相关阅读:
    MySQL---exists检查数据库对象是否存在
    MySQL---自查询
    MySQL---多表查询
    等待元素
    单元测试---testsuite对象
    mysql--事务
    untieeest方法
    线性,模块,数据,关键字的作用
    selenium中隐式等待和显示等待的区别
    软件测试的原则
  • 原文地址:https://www.cnblogs.com/sjrb/p/10371613.html
Copyright © 2020-2023  润新知