排序—时间复杂度为O(n)的三种排序算法
这三种排序算法分别是桶排序、计数排序和基数排序,之所以它们的时间复杂度能到达O(n),是因为它们都是非基于比较的排序算法,不涉及元素之间的比较操作。
1 桶排序
1.1 原理
将待排数据元素分配到几个有序的桶中,然后对每个桶中的数据元素分别进行排序,每个桶中的数据元素有序后按桶的顺序将数据元素依次取出,这样整个序列就有序。
1.2 算法分析
1.2.1 时间复杂度
假设待排序列数据元素个数为n,桶的数量为m;那么平均每个桶中的数据元素个数为k = n / m,对每个桶中的数据元素进行快速排序,那么每个桶中的时间复杂度为O(k * logk),也就是(n / m) * O(log (n / m)),总的时间复杂度为O(n * log(n / m));当桶的个数m接近数据元素个数时,那么log(n / m)就是一个常数,此时时间复杂度为O(n)。
1.2.2 空间复杂度
实现过程中,所有桶大小之和等于待排序列数据元素个数;对桶内数据元素进行排序时,可以使用快速排序和归并排序,快速排序的时间复杂度为O(1),归并排序的时间复杂度为O(n);所以桶排序的时间复杂度为O(n)。
1.2.3 稳定性
桶排序的稳定性与桶内元素排序算法是否稳定有关,如果桶内排序算法是稳定的,那么桶排序也是稳定的,反之,则桶排序不是稳定的。
1.2.4 适用场景
1)待排数据元素在一定区间内分布均匀,可以容易的划分到桶中,而且各个桶中的数据元素个数均匀;
2)桶排序比较适用于外部排序,外部排序就是当数据量过大,无法全部加载到内存中。
2 计数排序
2.1 原理
计数排序可以看成是特殊的桶排序。待排序序列有n个数据元素且数值范围不大,最大值为k,我们可以划分为k个桶,每个桶内的数据元素值相同,节省了桶内排序的时间。
2.2 算法分析
2.2.1 时间复杂度
计数排序的实现过程中,需要遍历两次序列,第一次从前往后划分数据元素,第二次从后往前重新排序,所以计数排序的时间复杂度为O(n)。
2.2.2 空间复杂度
计数排序过程中,首先需要长度为k+1的数组存储每个数值的元素个数,然后重新排序过程中,需要临时数组存放排序结果,所以计数排序的空间复杂度为O(n)。
2.2.3 稳定性
计数排序的实现过程中只有将原序列中数据元素存放到临时数组时会发生位置改变,但是实现使得并不会改变相同元素的相对位置,所以计数排序是稳定的。
2.3 适用场景
1)计数排序适合数据范围不大的场景;
2)计数排序只适合于非负整数排序,如果是其他数据类型,要在不改变其相对大小的情况下,将其转换为非负整数再进行排序。
3 基数排序
将数据元素划分出独立的位进行比较,而且位之间有递进关系,如果a的高位比b大,那么低位就不用进行比较了。除此之外,每一个位的数据范围不能太大,要可以用桶排序或者计数排序进行排序,这样基数排序的时间复杂度才为O(n)。例如,我们对10个电话号码进行排序,就可以使用基数排序算法。