计数排序是一种算法复杂度 O(n) 的排序方法,适合于小范围集合的排序。比如100万学生参加高考,我们想对这100万学生的数学成绩(假设分数为0到100)做个排序。我们如何设计一个 最高效的排序算法。本文不光给出计数排序算法的传统写法,还将一步步深入讨论算法的优化,直到时间复杂度和空间复杂度最优。

先看看计数排序的定义

Counting sort (sometimes referred to as ultra sort or math sort[1]) is a sorting algorithm which (like bucket sort) takes advantage of knowing the range of the numbers in the array to be sorted (array A). It uses this range to create an array C of this length. Each index i in array C is then used to count how many elements in A have the value i; then counts stored in C can then be used to put the elements in A into their right position in the resulting sorted array. The algorithm was created by Harold H. Seward in 1954.

计数排序是一个类似于桶排序的排序算法,其优势是对已知数量范围的数组进行排序。它创建一个长度为这个数据范围的数组C,C中每个元素记录要排序数组中对应记录的出现个数。这个算法于1954年由 Harold H. Seward 提出。

下面以示例来说明这个算法

假设要排序的数组为 A = {1,0,3,1,0,1,1}

这里最大值为3,最小值为0,那么我们创建一个数组C,长度为4.

然后一趟扫描数组A,得到A中各个元素的总数,并保持到数组C的对应单元中。

比如0 的出现次数为2次,则 C[0] = 2;1 的出现次数为4次,则C[1] = 4

由于C 是以A的元素为下标的,所以这样一做,A中的元素在C中自然就成为有序的了,这里我们可以知道 顺序为 0,1,3 (2 的计数为0)

然后我们把这个在C中的记录按每个元素的计数展开到输出数组B中,排序就完成了。

也就是 B[0] 到 B[1] 为0  B[2] 到 B[5] 为1 这样依此类推。

这种排序算法,依靠一个辅助数组来实现,不基于比较,算法复杂度为 O(n) ,但由于要一个辅助数组C,所以空间复杂度要大一些,由于计算机的内存有限,这种算法不适合范围很大的数的排序。

注:基于比较的排序算法的最佳平均时间复杂度为 O(nlogn)

Counting sort
Depends on a key assumption: numbers to be sorted are integers in{0, 1, . . . , k}.
Input: A[1 . . n], where A[ j ] ∈ {0, 1, . . . , k} for j = 1, 2, . . . , n. Array A and
values n and k are given as parameters.
Output: B[1 . . n], sorted. B is assumed to be already allocated and is given as a
parameter.
Auxiliary storage: C[0 . . k]
8-4 Lecture Notes for Chapter 8: Sorting in Linear Time
COUNTING-SORT(A, B, n, k)
for i ← 0 to k
do C[i ] ← 0
for j ← 1 to n
do C[A[ j ]] ← C[A[ j ]] + 1
for i ← 1 to k
do C[i ] ← C[i ] + C[i − 1]
for j ← n downto 1
do B[C[A[ j ]]] ← A[ j ]
C[A[ j ]] ← C[A[ j ]] − 1
Do an example for A = 21, 51, 31, 01, 22, 32, 02, 33
Counting sort is stable (keys with same value appear in same order in output as
they did in input) because of how the last loop works.

上面这段引自麻省理工大学计算机算法教材的技术排序部分,我不做翻译了。这个就是这个算法的典型解法,我把它作为方案1.

这个算法的实际扫描次数为 n+k (不包括写的次数)

方案1

        public static void Sort(int[] A, out int[] B, int k)
        {
            Debug.Assert(k > 0);
            Debug.Assert(A != null);
 
            int[] C = new int[k + 1];
            B = new int[A.Length];
 
            for (int j = 0; j < A.Length; j++)
            {
                C[A[j]]++;
            }
 
            for (int i = 1; i <= k; i++)
            {
                C[i] += C[i-1];
            }
 
            for (int j = A.Length - 1; j >= 0; j--)
            {
                B[C[A[j]]-1] = A[j];
                C[A[j]]--;
            }
 
        }

上面代码是方案1 的解法,也是计数排序算法的经典解法,麻省的教材上也是这样解。不过这个解法并不是最优的,因为空间复杂度还应该可以优化,我们完全可以不要那个输出的数组B,直接对A进行排序。在继续看方案2之前,我建议大家先自己思考一下,看看是否有办法省略掉数组B

方案2

我们对上述代码进行优化

        public static void Sort(int[] A, int k) { Debug.Assert(k > 0); Debug.Assert(A != null); int[] C = new int[k + 1]; for (int j = 0; j < A.Length; j++) { C[A[j]]++; } int z = 0; for (int i = 0; i <= k; i++) { while (C[i]-- > 0) { A[z++] = i; } } }

由于C数组下标 i 就是A 的值,所以我们不需要保留A中原来的数了,这个代码减少了一个数组B,而且要比原来的代码简化了很多。

和快速排序的速度比较

拿本文刚开始那个高考成绩的例子来做

            int[] A = new int[1000000];
            int[] B = new int[1000000];
 
            Random rand = new Random();
 
            for (int i = 0; i < A.Length; i++)
            {
                A[i] = rand.Next(0, 100);
            }
 
            A.CopyTo(B, 0);
 
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Array.Sort(B);
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
 
            sw.Reset();
            sw.Start();
 
            CountingSort.Sort(A, 100);
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);

输出结果

134 //快速排序
18   //计数排序

可见计数排序要比快速排序快将近6倍左右。

转载于:https://www.cnblogs.com/Simon-xm/p/3985433.html

算法——计数排序与快速排序相关推荐

  1. 三种线性排序算法 计数排序、桶排序与基数排序—— 转自:BYVoid

    三种线性排序算法 计数排序.桶排序与基数排序 [非基于比较的排序] 在计算机科学中,排序是一门基础的算法技术,许多算法都要以此作为基础,不同的排序算法有着不同的时间开销和空间开销.排序算法有非常多种, ...

  2. 三种线性排序算法 计数排序、桶排序与基数排序-BYVoid

    转自:BYVoid [非基于比较的排序] 在计算机科学中,排序是一门基础的算法技术,许多算法都要以此作为基础,不同的排序算法有着不同的时间开销和空间开销.排序算法有非常多种,如我们最常用的快速排序和堆 ...

  3. 排序算法——计数排序详解

    在排序的最终结果中,各元素的次序依赖于它们之间的比较.这类排序算法被称为比较排序.对于包含 nnn 个元素的输入序列来说,任何比较排序算法在最坏情况下都要经过至少 O(nlogn)O(n\ log\ ...

  4. 排序算法---计数排序(java版)

    计数排序 原理 计数排序(Counting Sort) 使用了一个额外的数组 C,其中第 i 个元素是待排序数组A 中值等于 i 的元素的个数.然后根据数组 C 来将 A 中的元素排到正确的位置.其实 ...

  5. 【vlfeat】O(n)排序算法——计数排序

    今天想在网上找一个实现好的er算法来着,没啥具体的资料,无奈只能看vlfeat的mser源码,看能不能修修补补实现个er. 于是,看到某一段感觉很神奇,于是放下写代码,跑来写博客,也就是这段 1 /* ...

  6. 数据结构与算法 | 计数排序

    之前的几篇讲解了所有常用的比较排序,这次就来讲一讲非比较排序的计数排序. 计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用.和其他排序不一样,计数排序并不是通过比较元素的大小来实现的,而是通过统计 ...

  7. C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序

    常见排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...

  8. 十大排序算法——计数排序

    计数排序 一. 计数排序介绍 二. 计数排序基础版 三. 计数排序改进版 四. 优化最终版本_空间节省 一. 计数排序介绍 计数排序(Counting sort)是一种稳定的排序算法.计数排序使用一个 ...

  9. 算法 - 计数排序(Counting_Sort)

    目录 引言: 学习: 什么是计数排序(Counting_sort)? 定义: 算法思想: 排序过程: Step 1 : Step 2 : Step 3 : Step 4 : Step 5 : 依次进行 ...

最新文章

  1. 热门云服务超87GB电子邮箱和密码泄露,黑客已验证大部分数据
  2. Windows服务ServicesDependedOn的奇怪问题?
  3. spock 集成测试_使用Spock 1.2简化对遗留应用程序的集成测试
  4. 解决win2003安装exchangeServer后关机慢的方法
  5. MyBatis动态传入表名,字段名参数的解决办法
  6. 想学好编程,别背代码!
  7. C# 结合 PInvoke 对接 IP 摄像头的笔记
  8. 系统分析师资料_软考 系统分析师考试通过总结
  9. 蓝桥杯 ADV-127 算法提高 日期计算
  10. CAD两条曲线如何连接成平滑的波浪线?
  11. 【QT小记】使用QPainter绘制各种基本图形
  12. 拼多多搜索热度怎么做|重庆乾胤
  13. adb 切换usb模式_adb调试命令,adb强制打开usb调试,adb命令打开usb调试
  14. 某移动版网页源码留存
  15. 神经网络训练样本的标签,训练图像识别神经网络
  16. idea配置有道翻译引擎
  17. html5诊断报告,网站诊断报告(模板).doc
  18. 用canvas画了个多啦A梦
  19. 《封号码罗》python爬虫之企某科技网站js逆向(十四)
  20. android DevAppsDirect开源项目

热门文章

  1. python爬虫入门教程-Python爬虫入门教程——爬取自己的博客园博客
  2. python第三方库安装-python的第三方库安装
  3. python是什么怎么用-python函数是什么,怎么用?【python培训】
  4. python输出数据到excel-python如何导出数据到excel文件
  5. python循环语句-python中的for循环语句怎么写
  6. python软件使用教程-python用什么软件编写
  7. python怎么读取列表-详解Python如何获取列表(List)的中位数
  8. python3-Python3 zip() 函数
  9. python条件语句-Python中条件判断语句的简单使用方法
  10. 在gitee下使用git克隆企业仓库