Arrays.sort()分析

Arrays.sort()分析

基本类型

对于基本类型,Java7前使用插入排序与快速排序,Java7之后引用双轴快速排序(DualPivotQuicksort)代替快速排序
当数组中元素小于7时,采用插入排序,尽管插入排序的时间复杂度为平方级,但是当数组元素较少时,插入排序优于快速排序
当数组中元素大于七时采用双轴快速排序算法。


双轴快速排序算法使用两个轴,通常选取最左边的元素作为pivot1和最右边的元素作pivot2,首先要比较这两个轴的大小,如果pivot1 > pivot2,则交换最左边的元素和最右边的元素,已保证pivot1 <= pivot2。
X  X  X  X  X  X  X  X  X   X  X  X  X  X  X  X
|   | <pivot1|>=pivot1&&<=pivot2|未计算|  >pivot2  |  |
pivot1     i                    k      j             pivot2
A[L+1, i]是小于pivot1的部分,A[i+1, k-1]是大于等于pivot1且小于等于pivot2的部分,A[j, R]是大于pivot2的部分,而A[k, j-1]是未知部分。和三向切分的快速排序算法一样,初始化i = L,k = L+1,j=R,k自左向右扫描直到k与j相交为止(k == j)。我们扫描的目的就是逐个减少未知元素,并将每个元素按照和pivot1和pivot2的大小关系放到不同的区间上去。
在k的扫描过程中我们可以对a[k]分为三种情况讨论(注意我们始终保持最左边和最右边的元素,即双轴,不发生交换)

(1)a[k] < pivot1 i先自增,交换a[i]和a[k],k自增1,k接着继续扫描

(2)a[k] >= pivot1 && a[k] <= pivot2 ,k自增1,k接着继续扫描

(3)a[k] > pivot2: 这个时候显然a[k]应该放到最右端大于pivot2的部分。但此时,我们不能直接将a[k]与j的下一个位置a[–j]交换,因为目前a[- -j]和pivot1以及pivot2的关系未知,所以我们这个时候应该从j的下一个位置(- -j)自右向左扫描。而a[- -j]与pivot1和pivot2的关系可以继续分为三种情况讨论
3.1)a[- -j] > pivot2,j自减1,j接着继续扫描
3.2)a[- -j] >= pivot1且a[j] <= pivot2 交换a[k]和a[j],k自增1,k继续扫描
3.3) a[- -j] < pivot1 先将i自增1,此时我们注意到a[j] < pivot1, a[k] > pivot2, pivot1 <= a[i] <=pivot2,那么我们只需要将a[j]放到a[i]上,a[k]放到a[j]上,而a[i]放到a[k]上。k自增1,然后k继续扫描
完成一次扫描后可以得到将首位的pivot1与 <pivot1区域的最后一个元素交换,pivot2与 >pivot2区域的第一个元素交换,随后对pivot1,pivot2分割开的三个区间进行递归操作。

对象类型

对于对象类型,Java7前使用归并排序,Java7之后引入TimSort算法。
对象类元素的通常包括许多变量,因此对于对象的排序,稳定性很重要。
TimSort算法把一个大数组,分为N部分来处理。先对第一部分数据排序(即0/N - 1/N),然后对第二部分数据进行排序(即1/N - 2/N),接着有序合并第一部分、第二部分数据,接下来对第三部分数据进行排序,有序合并第一部分、第二部分、第三部分数据。同样道理,对第四部分、…、第N部分数据进行处理,最终输出排序后的结果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值