计数排序和桶排序都只是在研究一个关键字的排序,现在我们来讨论有多个关键字的排序问题。
基数排序
方法;
从最低有效关键字开始排序,称为 LSD(Least Significant Dight)排序 。首先对所有的数据按照次要关键字排序,然后对所有的数据按照首要关键字排序。要注意的是,使用的排序算法必须是稳定的,否则就会取消前一次排序的结果。由于不需要分堆对每堆单独排序。
通常,基数排序要用到计数排序或者桶排序。使用计数排序时,需要的是Order数组。使用桶排序时,可以用链表的方法直接求出排序后的顺序
时间复杂度O(n)
(实际上是O(d(n+k))
d是位数)
桶排序
桶排序的思想近乎彻底的分治思想。
桶排序假设待排序的一组数均匀独立的分布在一个范围中,并将这一范围划分成几个子范围(桶)。然后基于某种映射函数f
,将待排序列的关键字 k
映射到第i
个桶中 (即桶数组B
的下标i
) ,那么该关键字k
就作为 B[i]
中的元素 (每个B[i]
都是一组大小为N/M
的序列 )。接着将各个桶中的数据有序的合并起来 : 对每个桶B[i]
中的所有元素进行比较排序 (可以使用快排)。然后依次枚举输出 B[0]....B[M]
中的全部内容即是一个有序序列。
平均时间复杂度为线性的 O(n+C)
最优情形下,桶排序的时间复杂度为O(n)
。
桶排序的空间复杂度通常是比较高的,额外开销为O(n+m)
(因为要维护 M 个数组的引用)。
就是桶越多,时间效率就越高,而桶越多,空间却就越大,由此可见时间和空间是一个矛盾的两个方面。
算法稳定性 : 桶排序的稳定性依赖于桶内排序。如果我们使用了快排,显然,算法是不稳定的。
对 N 个关键字进行桶排序的时间复杂度分为两个部分:
(1) 循环计算每个关键字的桶映射函数,这个时间复杂度是 O(n)
。
(2) 利用先进的比较排序算法对每个桶内的所有数据进行排序,其时间复杂度为 ∑ O(ni*logni)
。其中 ni
为第 i
个桶的数据量。
总结
关于稳定性:
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,
- 冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 常用时间复杂度的大小关系:
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)