Arrays排序代码阅读记录

201 阅读4分钟

Arrays中排序调用DualPivotQuicksort的sort方法。

  • DualPivotQuicksort 类注释中说明,该类方法只供程序包内部调用,在arrays中使用。

int[] 数组排序

  • 初始判断,如果数组长度<286,使用快速排序(QUICKSORT)leftmost = true ,默认范围在最左方

  • 进入快速排序方法(QUICKSORT),再次判断如果数组长度 <47 ,使用插入排序(INSERTION_SORT),并带入最初入参leftmost = true

  • 插入排序(INSERTION_SORT) 最初入参 leftmost = true,进入的代码区块如下

                for (int i = left, j = i; i < right; j = ++i) {
                    //i = 第一个数的下标
                    int ai = a[i + 1];//获取下一个数
                    while (ai < a[j]) { //下一个数小于当前数
                        a[j + 1] = a[j];//将当前数后移一位
                        if (j-- == left) {//至数组最前方
                            break;
                        }
                    }
                    a[j + 1] = ai;//将空出来的位置赋予ai
                }
  • 数组长度 >47 时排序方法
        // Inexpensive approximation of length / 7
        // 快速获取 长度/7 的值 ,位运算 1/7 = 1/8 + 1/64
        int seventh = (length >> 3) + (length >> 6) + 1;

        /*
        * Sort five evenly spaced elements around (and including) the
        * center element in the range. These elements will be used for
        * pivot selection as described below. The choice for spacing
        * these elements was empirically determined to work well on
        * a wide variety of inputs.
        */
       // e1 e2 e3 e4 e5 间隔 length/7 
       int e3 = (left + right) >>> 1; // The midpoint
       int e2 = e3 - seventh;
       int e1 = e2 - seventh;
       int e4 = e3 + seventh;
       int e5 = e4 + seventh;

   // Sort these elements using insertion sort
       //将 e1 e2 e3 e4 e5 先排序
       if (a[e2] < a[e1]) { int t = a[e2]; a[e2] = a[e1]; a[e1] = t; }

       if (a[e3] < a[e2]) { int t = a[e3]; a[e3] = a[e2]; a[e2] = t;
           if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
       }
       if (a[e4] < a[e3]) { int t = a[e4]; a[e4] = a[e3]; a[e3] = t;
           if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
               if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
           }
       }
       if (a[e5] < a[e4]) { int t = a[e5]; a[e5] = a[e4]; a[e4] = t;
           if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
               if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
                   if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
               }
           }
       }

   // Pointers 定义大小两个数组下标
       int less  = left;  // The index of the first element of center part
       int great = right; // The index before the first element of right part

准备工作结束,开始排序,首先判断选出来的四个节点不相等的情况

       //四个指针不相等
       if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
            /*
            * Use the second and fourth of the five sorted elements as pivots.
            * These values are inexpensive approximations of the first and
            * second terciles of the array. Note that pivot1 <= pivot2.
            */
           // e2 e4的值给两个指针
           int pivot1 = a[e2];
           int pivot2 = a[e4];
           
           /*
            * The first and the last elements to be sorted are moved to the
            * locations formerly occupied by the pivots. When partitioning
            * is complete, the pivots are swapped back into their final
            * positions, and excluded from subsequent sorting.
            */
           //将要排序的第一个和最后一个元素移到以前由枢轴占据的位置。 分区时完成后,枢轴将交换回其最终位置位置,并从后续排序中排除。
           a[e2] = a[left];
           a[e4] = a[right];
           
           /*
            * Skip elements, which are less or greater than pivot values.
            */
            //less 和 greate 和指针对比,找到前后第一个分割点,源码中官方给的图形象的说明了结果
           while (a[++less] < pivot1);
           while (a[--great] > pivot2);
           
           /*
            * 交换指针的值,之前赋值
            * int pivot1 = a[e2];
            * int pivot2 = a[e4];
            * a[e2] = a[left];
            * a[e4] = a[right];
            *
            * 由于a[++less] < pivot1 为false,pivot1 应至less前一位
            * */
           // Swap pivots into their final positions
           a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
           a[right] = a[great + 1]; a[great + 1] = pivot2;

           // Sort left and right parts recursively, excluding known pivots
           //将两部分数组分组递归排序
           sort(a, left, less - 2, leftmost);
           sort(a, great + 2, right, false);
           
           /*
            * If center part is too large (comprises > 4/7 of the array),
            * swap internal pivot values to ends.
            */
            //跳过相同数字
           if (less < e1 && e5 < great) {
               /*
                * Skip elements, which are equal to pivot values.
                */
               while (a[less] == pivot1) {
                   ++less;
               }

               while (a[great] == pivot2) {
                   --great;
               }
           }
           // Sort center part recursively
           //递归排序中间部分 学个英语单词recursively(递归的)
           sort(a, less, great, false);
       }
  • 接下来看 leftmost = false 进入的代码区块,最初进入先进行有序判断
               do {
                   if (left >= right) {
                       return;
                   }
               } while (a[++left] >= a[left - 1]);
               //初始判断数组是否已经是有序数组,如果数组每个数右边均大于左边,则数组为有序数组
  • 进入排序代码块,官方称此排序方法为配对插入排序(pair insertion sort)

待续。。。。