• 排序算法总结


    1. 冒泡排序

    // 朴素冒泡
    void bubble_sort_1(int n) {
        // 总共需要排序 n-1轮
        for(int i=n-1; i>=1; i--) {
            for(int j=0; j<i; j++) {
                if(s[j] > s[j+1])
                    swap(s[j], s[j+1]);
            }
        }
    }
    
    // 带优化的冒泡
    void bubble_sort_2(int n) {
        for(int i=n-1; i>=1; i--) {
            // 标记是否有序
            bool f = false;
            for(int j=0; j<i; j++) {
                if(s[j] > s[j+1])
                    swap(s[j], s[j+1]), f=true;
            }
            // 说明没有发生交换
            if(!f) break;
        }
    }
    

    2. 快速排序

    void quick_sort(int l, int r) {
        if(l >= r)
            return ;
        int i=l, j=r;
        int num = s[l];
        while(i < j) {
            // 从右面找比num小的
            while(i < j && s[j] > num) j--;
            // 从左面找比num大的
            while(i < j && s[i] < num) i++;
            // 交换
            if(i < j)
                swap(s[i], s[j]);
        }
        quick_sort(l, j-1);
        quick_sort(j+1, r);
    }
    

    3. 插入排序

    void insert_sort(int n) {
        // s[0]已经排序排好了
        for(int i=1; i<=n-1; i++) {
            int j = i-1;
            // j+1 即为要插的位置
            while(j >= 0 && s[j] > s[i])
                j--;
            int tmp = s[i];
            for(int k=i-1; k>=j+1; k--)
                s[k+1] = s[k];
            s[j+1] = tmp;
        }
        return ;
    }
    
    // 代码优化版本
    void insert_sort(int n) {
        // s[0]已经排序排好了
        for(int i=1; i<=n-1; i++) {
            int j = i-1;
            // j+1 即为要插的位置
            int tmp = s[i];
            while(j >= 0 && s[j] > tmp) {
                s[j+1] = s[j];
                j--;
            }
            s[j+1] = tmp;
        }
        return ;
    }
    

    4. 希尔排序

    void shell_sort(int n) {
        for(int gap = (n>>1); gap; gap>>=1) {
            // 共分gap个组
            for(int i=0; i<gap; i++) {
                for(int j=i+gap; j<n; j+=gap) {
                    int k = j - gap;
                    int tmp = s[j];
                    while(k >= i && s[k] > tmp) {
                        s[k+gap] = s[k];
                        k-=gap;
                    }
                    s[k+gap] = tmp;
                }
            }
        }
    }
    

    5. 选择排序

    void select_sort(int n) {
        // 共n-1轮次
        for(int i=0; i<n; i++) {
            int mn_pos = i;
            for(int j=i+1; j<n; j++) {
                if(s[j] < s[mn_pos]) {
                    mn_pos = j;
                }
            }
            if(i != mn_pos)
                swap(s[mn_pos], s[i]);
        }
        return ;
    }
    

    6. 堆排序

    这里比较trick的点就是,就是比如小根堆,根节点是最小的,因此呢,在排序的时候,s[0]和s[n]交换一下,排序结果就是从大到小的。
    想要从小到大的排序结果,需要用大根堆。

    // 对堆从st调整, 数组元素为n
    void heap_down(int st, int n) {
        int c = st;
        // 有左儿子
        while(2*c+1 <= n) {
            int l = 2*c+1;
            int mn = c;
            if(s[mn] > s[l])
                mn = l;
            if(l+1 <= n && s[mn] > s[l+1])
                mn = l+1;
            if(mn == c)
                break;
            swap(s[c], s[mn]);
            c = mn;
        }
        return ;
    }
    
    void heap_sort(int n) {
        for(int i=n/2; i>=0; i--)
            heap_down(i,n);
        for(int i=n; i>0; i--) {
            swap(s[i], s[0]);
            heap_down(0, i-1);
        }
        return ;
    }
    
    

    7. 归并排序

    void merge_sort(int l,int r) {
        if(l >= r)
            return ;
        int mid = (l+r)/2;
        merge_sort(l, mid);
        merge_sort(mid+1, r);
        int l1=l, l2=mid+1;
        int k = l;
        while(l1 <= mid && l2 <= r) {
            if(s[l1] > s[l2])
                t[k++] = s[l2++];
            else
                t[k++] = s[l1++];
        }
        while(l1 <= mid)
            t[k++] = s[l1++];
        while(l2 <= r)
            t[k++] = s[l2++];
        for(int i=l; i<=r; i++)
            s[i] = t[i];
        return ;
    }
    

    8. 分桶排序

    void bubble_sort(int n) {
        for(int i=0; i<n; i++) {
            t[s[i]]++;
        }
        int k = 0;
        for(int i=0; i<N; i++) {
            while(t[i]) {
                s[k++] = i;
                t[i]--;
            }
        }
        return ;
    }
    

    9. 基数排序

    int get_max(int n) {
        int mx = INT_MIN;
        for(int i=0; i<n; i++) {
            mx = max(mx, s[i]);
        }
        return mx;
    }
    // 对数组按照"某个位数"进行排序(桶排序)
    void count_sort(int n,int exp) {
        int output[n+5];
        int bucket[10]={0};
        for(int i=0; i<n; i++)
            bucket[ (s[i]/exp)%10] ++;
        // bucket[i] 现在存.. 当前位数为i的最后一个位置
        for(int i=1; i<10; i++)
            bucket[i] += bucket[i-1];
        // 从后面开始排是因为,每个在后面的数, 总有比他小的,所以在后面的先排
        for(int i=n-1; i>=0; i--) {
            output[bucket[(s[i]/exp)%10]-1] = s[i];
            bucket[(s[i]/exp)%10]--;
        }
        for(int i=0; i<n; i++)
            s[i] = output[i];
    }
    
    void radix_sort(int n) {
        int mx = get_max(n);
        for(int exp=1; mx /exp > 0; exp *= 10) {
            count_sort(n,exp);
        }
    }
    

    参考文章

    数据结构解析

  • 相关阅读:
    hystrix 源码分析以及属性的配置
    golang官方包限流器使用和原理(golang.org/x/time/rate)
    pip通过指定分支和子目录从git仓库中拉取python包
    cgo使用示例总结
    python装饰器原理和用法总结
    centos7编译安装clang8(同时还会编译llvm的不少东西, 文中附带编译好的二进制压缩包)
    prometheus+alertmanager+granafa监控总结,安装基于docker-compose(长期更新)
    go条件变量的使用和原理
    canal+kafka订阅Mysql binlog将数据异构到elasticsearch(或其他存储方式)
    go对elasticsearch的增删改查
  • 原文地址:https://www.cnblogs.com/Draymonder/p/10361428.html
Copyright © 2020-2023  润新知