http://blog.csdn.net/lingzhm/article/details/45022385
参考自:论文,Dual-Pivot Quicksort algorithm ,by Vladimir Yaroslavskiy。
http://www.sytarena.com/javajswz/20140217/1329.html
转载自:http://blog.csdn.NET/jy3161286/article/details/23361191?utm_source=tuicool
DualPivotQuicksort是JDK1.7开始的采用的快速排序算法。
一般的快速排序采用一个枢轴来把一个数组划分成两半,然后递归之。
大量经验数据表面,采用两个枢轴来划分成3份的算法更高效,这就是DualPivotQuicksort。
算法思想
选出两个枢轴P1和P2,需要3个指针L,K,G。
3个指针的作用如下图:
算法为以下的步骤:
1、小于27的数组,使用插入排序(或47)。
2、选择枢轴P1和P2。(假设使用数组头和尾)。
3、P1需要小于P2,否者交换。
现在数组被分成4份,left到L的小于P1的数,L到K的大于P1小于P2的数,G到rigth的大于P2的数,待处理的K到G的中间的数(逐步被处理到前3个区域中)。
4、L从开始初始化直至不小于P1,K初始化为L-1,G从结尾初始化直至不大于P2。K是主移动的指针,来一步一步吞噬中间区域。
****当大于P1小于P2,K++。
****当小于P1,交换L和K的数,L++,K++。
****当大于P2,如果G的数小于P1,把L上的数放在K上,把G的数放在L上,L++,再把K以前的数放在G上,G--,K++,完成一次L,K,G的互相交换。否则交换K和G,并G--,K++。
5、递归4。
6、交换P1到L-1上。交换P2到G+1上。
7、递归之。
JDK源码
流程图:
TimSort
直接调用的sort第一级:
- public static void sort(int[] a, int left, int right) {
- // Use Quicksort on small arrays
- if (right - left < QUICKSORT_THRESHOLD) {//门限为286
- sort(a, left, right, true);
- return;
- }
- /*
- * Index run[i] is the start of i-th run
- * (ascending&nbs***bsp;descending sequence).
- */
- int[] run = new int[MAX_RUN_COUNT + 1];
- int count = 0; run[0] = left;
- // Check if the array is nearly sorted
- for (int k = left; k < right; run[count] = k) {
- if (a[k] < a[k + 1]) { // ascending
- while (++k <= right && a[k - 1] <= a[k]);
- } else if (a[k] > a[k + 1]) { // descending
- while (++k <= right && a[k - 1] >= a[k]);
- for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
- int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
- }
- } else { // equal
- for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
- if (--m == 0) {
- sort(a, left, right, true);
- return;
- }
- }
- }
- /*
- * The array is not highly structured,
- * use Quicksort instead of merge sort.
- */
- if (++count == MAX_RUN_COUNT) {
- sort(a, left, right, true);
- return;
- }
- }
- // Check special cases
- if (run[count] == right++) { // The last run contains one element
- run[++count] = right;
- } else if (count == 1) { // The array is already sorted
- return;
- }
- /*
- * Create temporary array, which is used for merging.
- * Implementation note: variable "right" is increased by 1.
- */
- int[] b; byte odd = 0;
- for (int n = 1; (n <<= 1) < count; odd ^= 1);
- if (odd == 0) {
- b = a; a = new int[b.length];
- for (int i = left - 1; ++i < right; a[i] = b[i]);
- } else {
- b = new int[a.length];
- }
- // Merging
- for (int last; count > 1; count = last) {
- for (int k = (last = 0) + 2; k <= count; k += 2) {
- int hi = run[k], mi = run[k - 1];
- for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
- if (q >= hi || p < mi && a[p] <= a[q]) {
- b[i] = a[p++];
- } else {
- b[i] = a[q++];
- }
- }
- run[++last] = hi;
- }
- if ((count & 1) != 0) {
- for (int i = right, lo = run[count - 1]; --i >= lo;
- b[i] = a[i]
- );
- run[++last] = right;
- }
- int[] t = a; a = b; b = t;
- }
- }
2、大于286时,先使用TimSort的思想,找出正序或者倒序的数(run的栈),然后合并各个run,最后完成TimSort。
3、在找出run的时候,找出的run个数大于67时,即认为它是一个比较乱序的数组,就直接采用双枢轴快速排序。
双元素插入排序
下面看看双枢轴快速排序的实现(代码太长,分解之):
- /**
- * Sorts the specified range of the array by Dual-Pivot Quicksort.
- *
- * @param a the array to be sorted
- * @param left the index of the first element, inclusive, to be sorted
- * @param right the index of the last element, inclusive, to be sorted
- * @param leftmost indicates if this part is the leftmost in the range
- */
- private static void sort(int[] a, int left, int right, boolean leftmost) {
- int length = right - left + 1;
- // Use insertion sort on tiny arrays
- if (length < INSERTION_SORT_THRESHOLD) {//47个
- if (leftmost) {
- /* <li style="border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248, 248, 248); line-he