Java sort 源码解析 Object part

  上次分析了Java对primitive的排序,使用的是优化的快速排序算法。这次介绍Java对Object对象(Comparable)的排序。

Java使用了归并对Object排序,关于归并排序的细节,请查看http://zh.wikipedia.org/zh/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F

归并排序也有一个运行状态图,不过看着确实挺费解的 =。=!

merge_sort

 

在了解了归并排序的原理之后,我们展示Java的源码,来慢慢分析。

首先它克隆了一份拷贝,然后把拷贝和源数组都传入mergeSort方法。就是第一第二个参数。

另外3个参数分别是:low,high,off。low和high没啥多说的,就是上下界,不过off挺有意思的。这个变量没有,也不影响

排序的逻辑。为什么会有呢?先卖个关子。

 

这段看着非常熟悉,就是当长度小于INSERTIONSORT_THRESHOLD的时候,用插入排序。这个值,还是7.

大家如果还记得在快速排序中,直接hard coding了一个7。可见 sun 的程序员,也是会有失误的!大家都是人,中国程序员

只要不浮躁,还是能够很牛逼的。。。  有点扯远了。

其中的 swap() 就不再累述了。

 

接下来一段,是当长度大于7时,把数组分两端,分别递归排序。

细心的人已经发现了奥妙的地方,在外部调用mergeSort时,传入的参数顺序是 src, dest。可是它递归时,为什么传入dest,src呢?

位置互换到底代表什么呢?

试想,按照归并的本意,在比较开始之前,需要开辟一个新数组,长度是待比较的两数组和。不过在这Java的源码中,并没有发现这步。那是因为它有效的利用了空间,并没有开辟过多的空间。

大家还记得一开始克隆了数组吗?有了两个数组,他们在排序时,就能够互相利用彼此的空间。就不需要多开辟其他空间了。

下面我一步一步为大家讲解。

 

首先我们把原先的数组称作 O,克隆的数组称作C。

1.  外部调用mergeSort。按照 C,O的顺序传入。以O为Dest。如果小于7,将O插入排序便结束排序。如果大于7,进入2。待递归返回,将已排序的两部分C的结果,归并入O,结束排序。

 

2.  以1/2 C为Dest排序。如果C的某一半小于7,将C插入排序然后结束递归。如果大于7,进入3。待递归返回,将已排序的两部分O的结果,归并入C。将有序C返回。

 

3.  以1/4 O为Dest,继续mergeSort。。。。

。。。迭代ing。。。

 

n. 全部排序完毕之后,按照之前迭代相反的顺序,将结果归并。最终获得排序的数组O。

 

究竟怎么归并的呢?正好看下面一段代码。

 

在整个排序过程中,O和C的角色一直在src和dest中切换。这么做的目的只有一个,节约空间!

 

下面讲讲用Comparator。其实这个东西一点也不神奇。因为有些用户自定义的类,可能没有继承Comparable,所以sort时无法比较。

那么就可以写一个Comparator,来实现compareTo方法。目的就是告诉sort方法,两个对象,谁大谁小=。=  来帮助sort完成比较,并最终完成排序。

 

使用了Comparator的sort算法和上面的是基本一致的。就不累述了。

 

最后,off 这个变量我将揭开谜底!

因为有时,用户会对数组进行部分排序。那么就没必要克隆整个数组(Java对内存的开辟,真是太抠了。。。)。只要复制部分数组。

此时index在O和C就无法对应起来了。怎么办呢? off 变量就记录了这个偏移量,并且在迭代中起到控制的作用。

 

至此,Arrays sort的排序已经全部学习完毕,留此作为记录,待大家讨论,指点,也供比我更小白的小小白们学习。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值