Algorithm 线性排序算法

Algorithm 线性排序算法,algorithm,sorting,Algorithm,Sorting,我是学习算法的新手,也不是计算机科学专业的毕业生。 然而,在阅读线性排序非比较算法时,我可以理解基数排序是计数排序的扩展。 我不清楚的是计数排序的限制。 当计数排序似乎达到我需要避免O(n*logn)比较的目的时,我为什么要选择基数排序? 这似乎确实是一个简单得多的实现。当人们谈论算法时,他们通常表示算法在时间和内存需求方面的性能。 正如您所观察到的,计数排序非常好。它以线性时间运行。 但它也需要O(N)内存要求。 当我们寻找算法时,我们经常看到内存和时间复杂度之间的权衡。 通过使用更多内存,我

我是学习算法的新手,也不是计算机科学专业的毕业生。
然而,在阅读线性排序非比较算法时,我可以理解基数排序是计数排序的扩展。
我不清楚的是计数排序的限制。
当计数排序似乎达到我需要避免O(n*logn)比较的目的时,我为什么要选择基数排序?

这似乎确实是一个简单得多的实现。

当人们谈论算法时,他们通常表示算法在时间和内存需求方面的性能。
正如您所观察到的,计数排序非常好。它以线性时间运行。
但它也需要
O(N)
内存要求。
当我们寻找算法时,我们经常看到内存和时间复杂度之间的权衡。 通过使用更多内存,我们可以获得更好的运行时间。
因此,尽管计数排序具有更好的时间复杂度,但它需要与输入大小成比例的空间,这使得在大多数情况下无法使用。

作为一个更严重的问题,您需要事先知道输入中的数字范围。当然,对其进行编码既简单又优雅,但在实际使用中,它是有限的。

假设有人给了您一个整数列表进行排序。你对它一无所知,只知道它包含整数

如果幸运的话,列表中可能包含的数字范围很窄。如果您要对所有介于-100和100之间的整数进行排序,那么创建一个具有该大小的数组以进行计数排序将不会有任何问题

但是,如果一个数字非常大或非常小,您现在必须扩展数组的边界,以便对整个输入进行计数排序。如果确实要对所有可能的整数进行排序(并且在创建数组之前不知道值的范围,除非先找到它),则需要创建一个大小为
2*max_int
(对于负整数和正整数)的数组


基数排序很好,因为您不需要创建大于数字范围(0-9)的数组。

计数排序的复杂性为O(max-min),其中min,max是要排序的最小和最大整数。如果此范围远大于要排序的数组大小,则基数排序更好。

计数排序算法(包括基数)仅适用于可数元素。不幸的是,实数是不可数的,因此您无法轻松地对“float”或“double”值进行排序。假设您需要对测量的温度列表进行排序


现在,关于可数量(如整数),假设从数组中获取元素是O(1),则存在一个基本错误。事实并非如此。当数组大小为N时,将指针设置到此数组中的成本为O(log(N))。换句话说,要访问元素数组[i],需要定义“i”,要定义“i”的值,需要设置log(i)位。 只要N很小(例如,使用计数排序对-100到100之间的值进行排序时为200),我们就假设than log(N)是常数,忽略它。但是如果你想对整数进行排序,那么你的计数数组会很大(大小:2*MAX_INT),log(2*MAX_INT)可能是一个很大的数字(比如32)。 因此,假设您有一个大小为100:A[100]的整数数组。 使用O(N*log(N))排序需要进行O(100*log(100))比较。 但是,当使用计数排序时,您创建了一个巨大的计数数组(例如,对于64位整数为2^64),您的总时间是O(N*log(2^64)),这实际上大于O(100*log(100))。听起来很疯狂,但这是真的。 考虑一下,在开始计数之前,需要将整个计数数组设置为零,这是2^64个操作,比整个O(100*log(100))要多得多。。。 还要考虑一个巨大的内存浪费

总之:即使你有无限的内存来使用,运行时间也不是真的O(N)。实际上,这是将计数数组归零并执行计数的成本:

O(MAX_INT) + O(N*log(MAX_INT))
对于任何合理的N,这通常比O(N*log(N))多得多,因此计数排序是不切实际的。唯一可行的情况是当值的范围很小时 (比如-100..100)和

变成
O(200)+O(N*log(200))~O(N)


基数排序使您能够节省一些内存和将大量计数数组归零的成本,但仍然没有真正失去log()因子,因为许多范围-X..X具有log(X)位,并且仍然具有通常大于log(N)的log(MAX_INT),其中N是要排序的数组的大小

我不同意其中一些答案。第一个基数排序可以对double和float进行排序。我已经做到了,它仍然比比较排序快得多

对于op,你可以通过看我之前写的这篇文章了解更多。它永远是最好的线性时间排序


计数排序仅在可能值的范围相当狭窄时才起作用,即,如果要排序的值可能在0到2^32-1的范围内,这将不会非常有用,因为您需要许多GB的RAM。计数排序1、2、3将在非常不同的时间运行到1、2、783837。比较排序更容易预测。更准确地说,它的空间复杂度为O(max-min),但时间复杂度为O(数组大小)@Boris我总是假设分配空间需要空间量的线性时间,这只是我个人在复杂度分析中的偏好。好的观点:-)但是。。。要排序的数组的大小n可能仍然远远大于(max-min);-)。所以,如果分配是线性的,时间复杂度是O(max-min+n),或者如果分配是常数时间,时间复杂度是O(n)(这可能是可能的,向量的零初始化可以在常数时间内完成,如果我记得很清楚的话)“当数组大小为n时,将指针设置到此数组中的成本是O(log(n))”。您能进一步解释一下吗?假设您有一个大小为2^1000的数组。为了
O(MAX_INT) + O(N*log(MAX_INT))