zoukankan      html  css  js  c++  java
  • 读书日记- 线性时间排序算法

    在最坏情况下,任何比较排序算法都需要做O(nlgn)次比较。

    然而,在指定的条件下,线性时间的排序算法可以使得排序在O(n)时间内完成。

    计数排序

      假设n个输入元素中的每一个都是0到k区间内的一个整数,其中k为某个整数。k=O(n)时,排序运行时间为O(n)。

    主要思想:

      创建长度为k的数组C,将对应的输入数组A的值作为索引来统计k数组每个下标出现的次数。

    代码如下:

     

    void Counting_Sort(int* intArr,int* outArr,int k,int len)
    {
        int* cArr = new int[k];
        memset(cArr,0,k*sizeof(int));
        
        // 用cArr存储各个值出现次数
        for (int i=0; i<len; ++i) {
            cArr[intArr[i]] +=1;
        }
        
        // 存储当前值存在的话,所在的大小位数
        for (int i=1; i<k; ++i) {
            cArr[i]=cArr[i]+cArr[i-1];
        }
        
        for (int i=len-1; i>=0; --i) {
            outArr[cArr[intArr[i]]-1] =intArr[i];
            cArr[intArr[i]]-=1;
        }
        
        delete[] cArr;
    }

    基数排序

      假设对n个d位整数进行排序,从低到高位排,需要进行d轮排序。因为每位取值0~9,所以需要d次 k为9的排序方法计数排序。

    因而基数排序总时间为O(d(n+k))。

    代码如下:

       

    typedef struct _baseVar
    {
        int idx;
        int var;
    
    }BaseVar;
    
    // 调整后的计数排序
    void Counting_Sort_Ex(BaseVar* intArr, BaseVar* outArr, int k, int len)
    {
        int* cArr = new int[k];
        memset(cArr, 0, k*sizeof(int));
    
        // 用cArr存储各个值出现次数
        for (int i = 0; i<len; ++i) {
            cArr[intArr[i].var] += 1;
        }
    
        // 存储当前值存在的话,所在的大小位数
        for (int i = 1; i<k; ++i) {
            cArr[i] = cArr[i] + cArr[i - 1];
        }
    
        for (int i = len - 1; i >= 0; --i) {
            int nIdx = cArr[intArr[i].var]-1;
            outArr[nIdx].var = intArr[i].var;
            outArr[nIdx].idx = intArr[i].idx;
            cArr[intArr[i].var] -= 1;
        }
        delete[] cArr;
    }
    //
    void Radix_Sort(int* intArr, int d, int len)
    {
        BaseVar* varArr = new BaseVar[len];
        BaseVar* outArr = new BaseVar[len];
    
        // d位循环
        int div_var = 1;
        for (int j = 0; j<d; ++j) {
            for (int i = 0; i<len; ++i) {
                varArr[i].var = (intArr[i] % (div_var * 10)) / div_var;  //取每个位的值
                varArr[i].idx = i; //记录排序前的索引
            }
            // 计数排序
            Counting_Sort_Ex(varArr, outArr, 10, len);
            for (int i = 0; i<len; ++i) {
                varArr[i].var = intArr[outArr[i].idx]; //根据新索引赋值原来索引上的值
            }
            // 对应将原数组排序
            for (int i = 0; i<len; ++i) {
                intArr[i] = varArr[i].var;
            }
            div_var *= 10;
        }
    
        delete[] varArr;
        delete[] outArr;
    }


     

    桶排序

      假设输入数据服从均匀分布,平均情况下它的时间代价为O(n)。

    主要思想:

      对数据划分成n个大小相同的区间,称为桶。然后,将个输入按照映射函数f(k)尽量均匀分布到各个桶中。最后先分别对每个桶进行排序,

    然后遍历每个桶,并按照次序把每个桶中元素列出来即可。

    代码略。

  • 相关阅读:
    Spark机器学习基础三
    Spark机器学习基础二
    如何在Windows上的Jupyter Notebook中安装和运行PySpark
    Spark机器学习基础一
    基于卷积神经网络CNN的电影推荐系统
    相似度计算方法
    调参贝叶斯优化(BayesianOptimization)
    isStatic:检测数据是不是除了symbol外的原始数据
    获取当前页面url指定参数值
    Vue.js 运行环境搭建详解(基于windows的手把手安装教学)
  • 原文地址:https://www.cnblogs.com/stratrail/p/5046924.html
Copyright © 2011-2022 走看看