读书日记- 线性时间排序算法

在最坏情况下,任何比较排序算法都需要做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)尽量均匀分布到各个桶中。最后先分别对每个桶进行排序,

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

代码略。

原文地址:https://www.cnblogs.com/stratrail/p/5046924.html