计数排序

[算法分析]计数排序

|▌冷眼眸甩不掉的悲伤 提交于 2020-03-26 00:11:51
1. 计数排序的思想 我们之前接触过的例如:插入排序,归并排序,快速排序,堆排序等都是基于集合元素之间的比较这一基本的思想,它们执行的时间复杂度最优是趋于O(nlgn),而计数排序的运行机制不是基于集合元素之间的大小比较,什么???不做比较还能区分出元素之间的大小?是啊,算法就是这么伟大,我刚看它的时候也是激动不已呢。 计数排序的基本思想是:对每一个输入元素 x ,确定出小于 x 的元素个数。有了这一信息,就可以把 x 直接放到它在最终输出数组的位置上。 2. 计数排序的空间代价,假设原数组为:a[ 1...n ] 数组c[ k ] :提供临时存储区。这里 k 的定义为:a数组中每个元素都是介于 0 到 k 之间的整数,也可以将 k 想象成数组a中的最大值。 数组b[ n ] :存放排序结果。 注:这是一般的计数排序的空间消耗,我们可以通过一种方式,将这里存放排序结果的b数组省去,直接将最终排序的结果存在原数组a中,这个会在下面提到。 3. 计数排序的适用条件 计数排序是一个算法时间复杂度为θ( n )的排序方法,它适用于小范围集合的排序。这里的小范围是指 k = O(n),即 k 值不能太大。比如:我们要对全国高考学生的数学成绩进行排名,这里我们已经知道数学成绩是介于:0-150之间的,即这里的 k = 150 的,而高考学生的数量在900多万左右,这样的情况下可以达到很好的性能

【算法】计数排序、桶排序和基数排序详解

。_饼干妹妹 提交于 2020-03-23 20:37:02
01.计数排序、桶排序与基数排序 并不是所有的排序 都是基于比较的,计数排序和基数排序就不是。基于比较排序的排序方法,其复杂度无法突破 \(n\log{n}\) 的下限,但是 计数排序 桶排序 和基数排序是分布排序,他们是可以突破这个下限达到O(n)的的复杂度的 。 1. 计数排序 概念 计数排序是一种稳定的线性时间排序算法。计数排序使用一个额外的数组 C ,使用 C[i] 来计算 i 出现的次数。然后根据数 C 来将原数组A中的元素排到正确的位置。 复杂度 计数排序的最坏时间复杂度、最好时间复杂度、平均时间复杂度、最坏空间复杂度都是 O(n+k) 。n为元素个数,k为待排序数的最大值。 优缺点 计数排序不是比较排序,排序的速度优于任何比较排序算法。由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加1), 这使得对于数组中数据范围很大的数组,需要大量的时间和内存。 (简言之,不适于大范围数组) 通俗地理解,例如有10个年龄不同的人,统计出有8个人的年龄比A小,那A的年龄就排在第9位,用这个方法可以得到其他每个人的位置,也就排好了序。当然,年龄有重复时需要特殊处理(保证稳定性),这就是为什么最后要反向填充目标数组,以及将每个数字的统计减去1的原因。算法的步骤如下: 找出待排序数组中的最大元素和最小元素。 统计数组中值为 i 的元素出现的次数

线性排序:计数排序 Counting Sort 和 基数排序 Radix Sort

て烟熏妆下的殇ゞ 提交于 2020-03-22 00:04:12
3 月,跳不动了?>>> 基于比较的排序最好的时间复杂度为O(N*lgN),证明如下: 每种基于比较的排序都能够使用决策树描述其排序过程,每个节点最多有2个子节点。 该决策树的树叶的最大值即为所有可能的排序结果之和,即N的阶乘N!。 决策树的高度h即为比较的次数,因为二叉树节点数最多为2^h,所以有N! <= 2^h, 根据斯特林公式可知: h >= lgN! >= lg(N/e)^N = N*lg(N/e) = N*lgN - N*lge 因此算法复杂度最好为: O(N*lgN - N*lge) = O(N*lgN) 如果要追求效率更高的排序算法,比如线性排序,就要使用其他的非基于比较的排序算法。 本文用C实现了两种线性排序算法,分别为计数排序Counting Sort 和 基数排序 Radix Sort。这两种算法的实现要求排序元素为整数。 计数排序包括两步:计数和分配。首先对每个元素出现的次数进行计数,然后设置前缀数组得知每个元素在完成排序的数组中的位置,最后依照前缀数组进行元素分配。 可以证明,计数排序的时间复杂度为O(k+n),其中k为元素最大值,n为元素个数。 计数排序简单实现如下: /* Counting Sort include two steps: * Countint and Distribution. */ void countingSort(int arr[

计数排序

不羁的心 提交于 2020-03-21 23:50:19
3 月,跳不动了?>>> 1、思想 将数组元素作为数组下标,统计元素出现的个数。然后填充回原数组中。 2、时间复杂度 最好O(n ),最坏O(n ),平均O(n )。 3、代码实现 public class CountSort { public static void countSort(int[] arr){ if(arr == null || arr.length == 0) return; int n = arr.length; int max = arr[0]; //寻找数组的最大值 for(int i=1;i<n;i++){ if(max < arr[i]){ max = arr[i]; } } int[] temp = new int[max +1]; for(int i=0;i<=max;i++) temp[i] = 0; //进行计数 for(int i=0;i<n;i++){ temp[arr[i]]++; } int cur = 0; //进行数组填充 for(int i=0; i<=max; i++){ for(int j= temp[i];j>0; j--){ arr[cur++] = i; } } } public static void main(String[] args) { int[] arr = {50,10,90,30,70,40,80,60

数据结构-桶排序 计数排序 基数排序

眉间皱痕 提交于 2020-03-03 15:38:23
文章目录 桶排序(Bucket sort) 简介 时间复杂度 使用场景 计数排序(Counting sort) 简介 例子 代码实现 总结 基数排序(Radix sort) 简介 使用场景 代码实现 总结 注:所有的代码在我的 Github 中有均具体C++代码实现。 这里主要讲的是三大 线性排序 :桶排序(Bucket sort)、计数排序(Counting sort)和基数排序(Radix sort)。 所谓线性排序,也就是说时间复杂度为 O(n),而之所以能够做到线性排序,是因为这三个算法是 非基于比较 的排序算法,都不涉及元素之间的比较操作。 桶排序(Bucket sort) 简介 顾名思义,会用到“桶”,核心的思想就是将要排序的数据分到几个有序的桶里面,然后每个桶再进行单独的排序。桶内的数据排序过后,再把每个桶里面的数据依次取出,这样组成的序列就是有序的了。 时间复杂度 如果要排序的数据有 n 个,我们把它们均匀地划分到 m 个桶内,每个桶里就有 k=n/m 个元素。每个桶内部使用快速排序,时间复杂度为 O(k * logk)。m 个桶排序的时间复杂度就是 O(m * k * logk),因为 k=n/m,所以整个桶排序的时间复杂度就是 O(n*log(n/m))。当桶的个数 m 接近数据个数 n 时,log(n/m) 就是一个非常小的常量,这个时候桶排序的时间复杂度接近

桶排序和计数排序

心不动则不痛 提交于 2020-02-28 00:42:03
突然想自己写个桶排序,然后做课后题又发现了计数排序,觉得挺有趣的。不过书上都没有给代码,所以就自己写了一下代码,超级烂0 0下面先简单介绍下这两种排序 桶排序 桶排序,就是根据散列的思想进行数据的排序。假设有M个桶,采用最简单的hash(key)=key,这样无需比较,就可以把数存入相应的桶中。针对冲突排解问题,此时查找链的方式显然不再适用,采用独立链法,把每个桶以链表的形式存储雷同元素,定义相同元素的偏序,这样能实现排序的稳定性。桶排序完全采用了简单的哈希策略,是比较容易理解的。同时,完全摒弃了CBA式的方式,从而可以突破复杂度O(nlogn)的界限。通过空间换时间的策略,可以达到O(n)的时间复杂度,代价是O(M+N)的额外空间。下面是对于整型数组的桶排序,代码很烂我也没有改,已经测试过: 1 struct node 2 { 3 node(int v = 0, node* s = NULL) :value(v), succ(s) {} 4 int value; 5 node* succ; 6 }; 7 void insert(node &a, int b)//b插入到a后面 8 { 9 node* t = new node(b); 10 if (a.succ) t->succ = a.succ; 11 a.succ = t; 12 } 13 node* bucketSort

计数排序

为君一笑 提交于 2020-02-26 10:29:59
如何给50万高考考生的成绩进行排序? 初识计数排序 当初我17年高考的时候,提说四川考生有5 大专栏 计数排序 0万,竞争十分激烈,虽然现在我已不记得了我当初在四川省的排名,但是我可以去学习怎么对这50万考生的成绩进行排序,话不多说,开始吧。 高考的满分是760分,所以我们就设置761个容器,根据每个考生成绩,将50万考生分别放进这761个容器内。每个容器内装的都是成绩相同的考生,所以就不需要对容器内的考生再进行一次排序了。 来源: https://www.cnblogs.com/liuzhongrong/p/12365340.html

十大排序算法

a 夏天 提交于 2020-02-13 02:02:07
好好学习算法基础 0、排序算法说明 0.1 排序的定义 对一序列对象根据某个关键字进行排序。 0.2 术语说明 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面; 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面; 内排序 :所有排序操作都在内存中完成; 外排序 :由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行; 时间复杂度: 一个算法执行所耗费的时间。 空间复杂度 :运行完一个程序所需内存的大小。 0.3 算法总结 图片名词解释: n: 数据规模 k: “桶”的个数 In-place: 占用常数内存,不占用额外内存 Out-place: 占用额外内存 0.5 算法分类 0.6 比较和非比较的区别 常见的 快速排序、归并排序、堆排序、冒泡排序 等属于 比较排序 。 在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置。 在 冒泡排序 之类的排序中,问题规模为n,又因为需要比较n次,所以平均时间复杂度为O(n²)。在 归并排序、快速排序 之类的排序中,问题规模通过 分治法 消减为logN次,所以时间复杂度平均 O(nlogn) 。 比较排序的优势是,适用于各种规模的数据,也不在乎数据的分布,都能进行排序。可以说, 比较排序适用于一切需要排序的情况。 计数排序、基数排序

计数排序

梦想的初衷 提交于 2020-02-03 11:54:41
计数排序 一、比较计数排序 1、描述 针对待排序列表中的每一个元素,算出列表中小于该元素的元素个数,并把结果记录在一张表中。这个“个数”指出了该元素在有序列表中的位置,因此,我们可以简单地把列表的元素复制到它在有序新列表中的相应位置上,来对列表进行排序。 例如,对于可排序数组为array=[34, 62, 28, 73, 51, 46],利用计数排序算法对其排序过程如下图所示。 2、算法(伪代码) ComparisonCountingSort (A[0..n-1]) //用比较计数法对数组排序 //输入:可排序数组A[0..n-1] //输出:将A中元素按照升序排列的数组S[0..n-1] for i←0 to n-1 do Count[i]←0 for i←0 to n-2 do for j←i+1 to n-1 do if A[i]>A[j] Count[i]←Count[i]+1 else Count[j]←Count[j]+1 for i←0 to n-1 do S[Count[i]]←A[i] return S 3、源代码(Java语言) /** * Project: Algorithm * Date: 2020/02/02 * Time: 20:20 * author: Eric * Description: TODO 计数排序 */ public class

计数排序

北城余情 提交于 2020-01-31 14:42:27
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。 def countSort(arr): output = [0 for i in range(256)] count = [0 for i in range(256)] ans = ["" for _ in arr] for i in arr: count[ord(i)] += 1 for i in range(256): count[i] += count[i-1] for i in range(len(arr)): output[count[ord(arr[i])]-1] = arr[i] count[ord(arr[i])] -= 1 for i in range(len(arr)): ans[i] = output[i] return ans arr = "wwwrunoobcom" ans = countSort(arr) print ( "字符数组排序 %s" %("".join(ans)) ) 结果符数组排序 bcmnoooruwww 参考https://www.runoob.com/python3/python3-examples.html 来源: https://www.cnblogs.com/xingnie/p