Collections.sort()
和 Arrays.sort()
的默认排序算法是基于 TimSort 的混合排序算法。TimSort 是一种结合了 归并排序(Merge Sort) 和 插入排序(Insertion Sort) 的优化算法。
1. TimSort 的核心思想
TimSort 的核心思想是 利用数据的局部有序性,通过以下步骤实现高效排序:
-
分块(Run) :
- 将数组分成多个 有序的子数组(Run) 。
- 如果子数组长度小于某个阈值(默认为 32),则使用插入排序将其扩展为更长的有序子数组。
-
合并(Merge) :
- 使用归并排序的合并方法,将多个有序子数组合并成一个有序数组。
- 合并过程中,TimSort 会尽量利用已有的有序性,减少比较和移动的次数。
2. TimSort 的优势
-
适应性强:
- 对于部分有序的数据,TimSort 的性能接近 O(n)。
- 对于随机数据,TimSort 的性能为 O(n log n)。
-
稳定性:
- TimSort 是稳定排序算法,相同元素的相对顺序不会改变。
-
空间复杂度:
- TimSort 的空间复杂度为 O(n),但在实际应用中,由于优化措施,额外空间通常较小。
3. Java 中的 TimSort 实现
在 Java 中,Collections.sort()
和 Arrays.sort()
的默认排序算法是基于 TimSort 的。以下是相关源码的调用链:
-
Collections.sort()
:javapublic static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null); }
-
List.sort()
:javadefault void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }
-
Arrays.sort()
:javapublic static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }
-
TimSort.sort()
:- 这是 TimSort 的核心实现,负责分块、插入排序和归并排序。
4. TimSort 的适用场景
-
部分有序数据:
- TimSort 在部分有序数据上的性能优于传统的归并排序和快速排序。
-
稳定排序需求:
- 如果需要保持相同元素的相对顺序,TimSort 是一个理想选择。
-
通用排序:
- 由于 TimSort 的综合性能优异,Java 将其作为默认排序算法。
5. TimSort 的时间复杂度
情况 | 时间复杂度 |
---|---|
最好情况 | O(n) |
最坏情况 | O(n log n) |
平均情况 | O(n log n) |
~~Summary
- Java 的
Collections.sort()
和Arrays.sort()
默认使用 TimSort 算法。 - TimSort 是一种结合了归并排序和插入排序的混合算法,具有稳定性和高效性。
- 它在部分有序数据上的性能接近 O(n),在随机数据上的性能为 O(n log n)。