数据结构与算法系列之常用算法:排序算法


〇、前言

<<>>

一、排序算法

下面常用排序算法的动图都是从网络挑选的好理解的动图。

01、冒泡排序

02、选择排序

03、插入排序

04、希尔排序


05、快速排序


06、归并排序

07、堆排序

08、计数排序

09、桶排序


10、基数排序


二、Java排序

1、DualPivotQuicksort.sort

根据数组的元素个数、nearly sorted和元素类型等来选择具体排序算法。例如对整数排序:

if (元素个数 < 47) {
    插入排序
    return;
} 
if (元素个数 < 286) {
    双轴快排
    return;
} 
// 判断数组是否是nearly sorted:统计数组中有序段的个数(包括正序和逆序),
// 如果有序段的个数 < 67,那么说明数组是nearly sorted,使用归并排序,归并所有有序段;
// 否则,说明数组不是nearly sorted,使用双轴快排
if (nearly sorted) {
    归并排序
} else {
    双轴快排
}

2、Arrays.legacyMergeSort

一个遗留个归并排序算法,未来的版本中将会淘汰,这里不予探究。

3、Timsort.sort | ComparableTimSort.sort

二分插入,一种优化的插入排序:标准插入排序是循环遍历查找元素的插入位置,而二分插入则是通过二分查找来找到元素的插入位置。

Timsort简单来说就是,分段 -> 利用插入排序(通过头部有序序列和二分插入优化)使其有序 -> 将有序段归并 -> 完成排序

4、为何Java不使用堆做纯排序

  1. 从cpu缓存的角度,堆是跳跃操作数组的,无法利用cpu缓存预读;
  2. 从nearly sorted角度,如果一个数组很多部分都是有序的,使用堆排序,会将其先打散,反而效率不如快速排序和归并排序;
  3. 堆是用数组实现的,要求内存连续,数据量大的时候不合适;

三、总结

JDK提供的排序算法很好,根据自己特定场景选择用JDK的还是自己实现。