线性时间排序

计数排序

耗时Θ(n)

  1. 计数排序需要首先确定数组A中数据的范围,然后统计在每个位置上数据出现的个数,将其保存在一个与数据范围等大的数组C中。
  2. 然后对C进行累加,这样C[i]的值,便可以当作输出数组B中数值i的位置。
  3. 对A中的每一个数据,通过C[A[j]]-1,得到在B中的位置,同时对C[A[j]]--,以便下次出现相同值时有正确的位置
static void CountingSort(List<int> sq,out List<int> result, int k)
{
    List<int> count = new List<int>();
    result = new List<int>(sq);
    for (int i = 0; i < k; i++)
    {
        count.Add(0);
    }
    //统计每个数出现的次数
    foreach (int value in sq)
    {
        count[value]++;
    }
    //将次数累加
    for (int i = 1; i < k; i++)
    {
        count[i] += count[i - 1];
    }
    //输出到result
    for (int i = sq.Count - 1; i >= 0; i--)
    {
        //result-1在这里保存的就是sq[i]在result的位置了
        result[count[sq[i]]-1] = sq[i];
        count[sq[i]]--;
    }
}

基数排序

  1. 在比较日期的时候,我们可以先比较年,再比较月,再比较日,或者日月年。其中日、月、年就是3个基数。
  2. 我们在比较数字的时候,可以将每一位进行比较,然后再排序时。
  3. 基数排序对于相同的基数,要保证其他位置在排序后相对位置不变,也就是稳定排序方法(例如125,223,124,123,个位排序后应该为223,123,124,125,而非123,223,124,125,技术排序中对出现的次数累加然后输出就可以保证这个性质)。
  4. 对于二进制数据基数的大小为2

基数排序中如果稳定排序方法耗时Θ(n+k),n个数k个可能取值,那么Θ(d(n+k))为基数排序时间代价,d是基数个数。

桶排序

耗时Θ(n)

  1. 假设输入的集合A有n个数据,在[0,1)内均匀分布
  2. 创建链表的集合B,含有n个空链表
  3. 将A[i]存入链表B[int(n*A[i])]
  4. 对链表排序
  5. 合并链表中的数据
private static void BucketSort(List<double> sequence)
{
    //创建桶
    List<List<double>> bucket = new List<List<double>>();
    for (int i = 0; i < sequence.Count; i++)
        bucket.Add(new List<double>());
    //数据如桶
    foreach (double a in sequence)
    {
        bucket[(int)(sequence.Count * a)].Add(a);
    }
    //合并桶
    int index = 0;
    foreach (var a in bucket)
    {
        //排序每个桶中的元素
        a.Sort();
        foreach (var aa in a)
            sequence[index++] = aa;
    }
}
原文地址:https://www.cnblogs.com/qiusuo/p/5211473.html