时间复杂度和空间复杂度对比
平均时间复杂度 | 最好 | 最坏 | 空间复杂度 | 排序方式 | 稳定性 | |
---|---|---|---|---|---|---|
冒泡排序 | O(n2) | O(n) | O(1) | |||
选择排序 | O(n2) | O(1) | × | |||
插入排序 | O(n2) | O(n) | O(1) | |||
希尔排序 | O(nlogn) | O(nlog2n) | O(nlog2n) | O(1) | × | |
归并排序 | O(nlogn) | O(n) | ||||
快速排序 | O(nlogn) | O(n2) | O(nlogn) | × | ||
堆排序 | O(nlogn) | O(1) | × | |||
计数排序 | O(n+k) | O(k) | ||||
桶排序 | O(n+k) | O(n2) | O(n+k) | |||
基数排序 | O(n*k) | O(n+k) |
冒泡排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
选择排序
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
插入排序
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
希尔排序
- 选择一个增量序列 t1,t2,……,tk,其中 ti > tj(i<j), tk = 1;
- 按增量序列个数 k,对序列进行 k 趟排序;
- 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
归并排序
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
快速排序
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
堆排序
升序-大顶堆,降序-小顶堆
- 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
- 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
- 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
计数排序
- 找出待排序的数组中最大和最小的元素;
- 统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
- 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
- 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
桶排序
宗旨:将数组分到有限数量的桶里(每个桶大小相等),再对每个桶分别排好序
- 首先确定桶的个数。因为桶排序最好是将数据均匀地分散在各个桶中,那么桶的个数最好是应该根据数据的分散情况来确定。首先找出所有数据中的最大值mx和最小值mn;
- 根据mx和mn确定每个桶所装的数据的范围 size,有
size = (mx - mn) / n + 1
,n为数据的个数,需要保证至少有一个桶,故而需要加个1 - 求得了size即知道了每个桶所装数据的范围,还需要计算出所需的桶的个数cnt,有
cnt = (mx - mn) / size + 1
,需要保证每个桶至少要能装1个数,故而需要加个1; - 求得了size和cnt后,即可知第一个桶装的数据范围为
[mn, mn + size)
,第二个桶为[mn + size, mn + 2 * size),
…,以此类推,因此步骤2中需要再扫描一遍数组,将待排序的各个数放进对应的桶中。 - 对各个桶中的数据进行排序,可以使用其他的排序算法排序,例如快速排序;也可以递归使用桶排序进行排序;
- 将各个桶中排好序的数据依次输出,最后得到的数据即为最终有序。
基数排序
重点是按照“个,十,百,分别排序”
- 待排序记录以指针相链,构成一个链表
- “分配” 时,按当前“关键字位”所取值,将记录分配到不同的“链队列” 中,每个队列中记录的 “关键字位” 相同;
- “收集”时,按当前关键字位取值从小到大将各队列首尾相链成个链表;
- 对每个关键字位均重复 2) 和 3)两步
数字的d为10,字母的d为26