zoukankan      html  css  js  c++  java
  • 《啊哈!算法》第7章 神奇的树

    第3节 堆排序

    把n个元素建立一个堆,首先将这n个结点以自顶向下、从左到右的方式从1到n编码,这样可以把n个结点转换成一颗完全二叉树

    紧接着从最后一个非叶子结点(结点编号为n/2)开始到根节点(结点编号为1),逐个扫描所有结点,根据需要将当前结点向下调整,直到以当前结点为根结点的子树符合堆的特性。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    
    //向下调整函数
    void shiftdown(vector<int>& a, int n,int index){
        while(index*2<= n ){
            int t = index;
            if(a[t] > a[2*index]) t = 2*index;
            if( 2*index+1 <= n &&  a[t] > a[2*index+1] ) t = 2*index+1;
            if(t!=index) {swap(a[t],a[index]); index = t;}
            else break;
        }
    }
    
    //删除最大的元素
    int deletemax(vector<int>& a , int& n){
        int res = a[1];
        swap(a[1],a[n]);
        n--;
        shiftdown(a,n,1);
        return res;
    }
    
    //向上调整函数
    void shiftup(vector<int>& a, int n, int index){
        if(index == 1) return;
        while(index!=1){
            if(a[index] < a[index/2]) swap(a[index],a[index/2]);
            else break;
            index/=2;
        }
    
    }
    
    // 创建堆
    void make_heap(vector<int>& a, int n){
        //注意索引是从0开始的
        for(int i = n/2; i> 0; -- i){
            shiftdown(a,n,i);
        }
        
    }
    
    void heap_sort(vector<int>& a){
        int n =a.size()-1;
        while( n > 1){
            swap(a[1],a[n]);
            n--;
            shiftdown(a,n,1);
        }
    }
    
    int main(){
        int n;
        cin >> n;
        vector<int> a(n+1,0);
        for(int i = 1 ; i <= n; ++ i){
            cin >> a[i];
        }
    
        //建堆
        make_heap(a,n);
    
        heap_sort(a);
        
        for(int i = 1 ; i <= n; ++ i){
            cout<<a[i]<<" ";
        }    
        cout<<endl;
        int num = n;
        for(int i = 1; i <= n; ++ i){
            cout<<deletemax(a,num)<<endl;
        }
    
    }
    堆排序

     第4节 并查集

    并查集的优化有两种,一种是路径压缩,一种是按秩合并,具体的可以参考《算法导论》

    /*
     *并查集操作
     */
    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int f[1000]={0};
    
    void make_set(int size){
        for(int i =1; i <= size; ++ i ) f[i] = i;
    }
    
    
    //采用路径压缩的方法查找元素
    int find_set(int x){
        if(f[x] == x) return x;
        else{
             f[x] = find_set(f[x]);  //查找x元素所在的集合,回溯时压缩路径
             return f[x];
        }
    
    }
    
    void union_set(int x, int y){
        int t1 = find_set(x), t2 = find_set(y);
        if(t1 != t2){
            f[t2] = t1;
        }
    }
    
    int main(){
        int n, m;
        cin >> n >> m;
        make_set(n);
        for(int i = 1; i<=m; ++ i){
            int x,y;
            cin >> x >> y;
            union_set(x,y);
        }
        int sum = 0;
        for(int i = 1; i<= n; ++ i){
            if(f[i] == i) sum++;
        }
        cout<<sum<<endl;
        return 0;
    }
    并查集
  • 相关阅读:
    3.1《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——下载文件
    rem实现手机页面自动缩放
    Git 常用命令
    使用 canvas+JS绘制钟表
    JS 操作数组的方法
    Node.js Request方法
    兼容浏览器的点击事件
    ES6知识点
    上传项目到github上
    JavaScript 编码风格
  • 原文地址:https://www.cnblogs.com/xiongqiangcs/p/3809846.html
Copyright © 2011-2022 走看看