合并排序和快速排序

2019-07-17  本文已影响0人  ZuYuan
  • 合并排序:θ(nlogn)
  • 快速排序:一般是O(nlogn)
    /**
     * 合并排序
     */
    public static void mergeSort(int[] nums) {
        final int length = nums.length;
        if (length > 1) {
            int aLength = length >> 1;
            int bLength = length - aLength;
            int a[] =  new int[aLength];
            int b[] = new int[bLength];
            System.arraycopy(nums, 0,a, 0, aLength);
            System.arraycopy(nums, aLength, b, 0, bLength);

            mergeSort(a);
            mergeSort(b);
            merge(a, b, nums);
        }
    }

    /**
     * 合并a、b两个有序数组到old中
     * @param a 待合并有序数组
     * @param b 待合并有序数组
     * @param old 合并目标数组
     */
    public static void merge(int[] a, int[] b, int old[]) {
        int aIndex = 0, bIndex = 0, oldIndex = 0;
        while (aIndex < a.length && bIndex < b.length) {
            if (a[aIndex] <= b[bIndex]) {
                old[oldIndex] = a[aIndex];
                aIndex++;
            } else {
                old[oldIndex] = b[bIndex];
                bIndex++;
            }
            oldIndex++;
        }

        //把剩下还未放入old数组中的元素放进去
        if (aIndex == a.length) {
            System.arraycopy(b, bIndex, old, oldIndex, old.length - oldIndex);
        } else {
            System.arraycopy(a, aIndex, old, oldIndex, old.length - oldIndex);
        }
    }

  /* ---------------------------------------------------------------------------*/

    /**
     * 快速排序一般考虑的是数组比较大的情况
     * 在数组元素很少的情况下应考虑插入排序
     * 或者说在子数组元素在5~15个的时候改用插入排序
     */
    public static void fastSort(int[] nums,int startIndex, int endIndex) {
        //数组长度小于10时采用插入排序
        if (endIndex- startIndex < 10) {
            insertionSort(nums);
        } else {
            //找到中值,并和首值交换
            //如果只采用快排的话,请加上下面一句话,不然会数组下标越界
            //if((endIndex - startIndex) < 2) return;
            int centreIndex = selectCentreIndex(nums, startIndex, endIndex);
            swap(nums, startIndex, centreIndex);
            int partitionCentreIndex = theHoarePartition(nums, startIndex, endIndex);
            fastSort(nums, startIndex, partitionCentreIndex - 1);
            fastSort(nums, partitionCentreIndex, endIndex);
        }
    }

    /**
     * 这里使用三平均划分法
     * 还有随机划分法
     */
    private static int selectCentreIndex(int[] nums, int startIndex, int endIndex){
        int centreIndex = ((endIndex - startIndex) >> 1) + startIndex;
        int a = nums[startIndex];
        int b = nums[endIndex];
        int c = nums[centreIndex];

        int result;
        if (a > c) {
            if (b > a) {
                result = startIndex;
            } else {
                if (b > c) {
                    result = endIndex;
                } else {
                    result = centreIndex;
                }
            }
        } else {
            if (b > c) {
                result = centreIndex;
            } else {
                if (b > a) {
                    result = endIndex;
                } else {
                    result = startIndex;
                }
            }
        }
        return result;
    }

    /**
     * 交换a, b下标对应元素的位置
     */
    private static void swap(int nums[], int aIndex, int bIndex) {
        int c = nums[aIndex];
        nums[aIndex] = nums[bIndex];
        nums[bIndex] = c;
    }

    /**
     * 霍尔划分
     * 以首元素为中值实现数组划分
     */
    private static int theHoarePartition(int[] nums, int startIndex, int endIndex) {
        int centreIndex = startIndex;
        int centreValue = nums[startIndex];
        startIndex++;
        while (startIndex <= endIndex) {
            while (nums[startIndex] <= centreValue) startIndex++;
            while (nums[endIndex] >= centreValue) endIndex--;
            swap(nums, startIndex, endIndex);
        }
        //撤销最后一次交换
        swap(nums,startIndex, endIndex);
        //将中值交换到数组中间来(左小右大)
        swap(nums, centreIndex, endIndex);
        return endIndex;
    }

上一篇下一篇

猜你喜欢

热点阅读