Java快速排序

整体结构

/**
 * 快速排序
 *
 * @author 小流慢影
 * @date 2023年3月16日
 */
public class Quicksort {

    public static void main(String[] args) {
        int[] array = {5, 4, 3, 1, 2, 13, 12, 10, 11, 9, 7, 8, 6, 3, 5};
        System.out.println("原数组:" + Arrays.toString(array));
        quicksort(array, 0, array.length - 1);
        System.out.println("排序后数组:" + Arrays.toString(array));
    }

    public static void quicksort(int[] array, int startIndex, int endIndex) {
        if (startIndex >= endIndex) {
            return;
        }

        // 具体排序,返回中心点(pivot)下标,下面单独展示具体排序算法
        int pivotIndex = specificSort(array, startIndex, endIndex);

        // 对中心点左端的数组进行递归排序
        quicksort(array, startIndex, pivotIndex - 1);
        // 对中心点右端的数组进行递归排序
        quicksort(array, pivotIndex + 1, endIndex);
    }
}

具体排序算法

双指针-交换法
/**
 * 具体排序
 * 本方法采用 双指针-交换法
 *
 * @param array      待排数组
 * @param startIndex 开始下标
 * @param endIndex   结束下标
 * @return 中心点(pivot)下标
 */
private static int specificSort(int[] array, int startIndex, int endIndex) {
    /*
     * 这里将最左边位置设为中心点
     * 如果将最左边的作为起始点,则下面循环一定要右侧先走,否则会出现循环完毕后,左右互换点的值大于中心点,然后又被置换到最左侧了,引起排序异常
     * 同理,如果将最右边的作为起始点,则下面循环一定要左侧先走;
     */
    int pivot = array[startIndex];
    int leftPointer = startIndex;
    int rightPointer = endIndex;

    while (leftPointer < rightPointer) {
        // 因为上面是将最左边位置设为了中心点,所以右侧先走
        while (leftPointer < rightPointer && array[rightPointer] >= pivot) {
            rightPointer--;
        }
        while (leftPointer < rightPointer && array[leftPointer] <= pivot) {
            leftPointer++;
        }

        // 左右互换
        if (leftPointer < rightPointer) {
            int temp = array[leftPointer];
            array[leftPointer] = array[rightPointer];
            array[rightPointer] = temp;
        }
    }

    // 左右指针相等时,将pivot换到这个位置来
    array[startIndex] = array[leftPointer];
    array[leftPointer] = pivot;
    return leftPointer;
}
双指针-挖坑法
/**
 * 具体排序
 * 本方法采用 双指针-挖坑法
 *
 * @param array      待排数组
 * @param startIndex 开始下标
 * @param endIndex   结束下标
 * @return 中心点(pivot)下标
 */
private static int specificSort(int[] array, int startIndex, int endIndex) {
    // 这里将最左边的值设为中心点,同时,也创建了一个“坑”,后面的值可以直接填在这个“坑”里
    int pivot = array[startIndex];
    int leftPointer = startIndex;
    int rightPointer = endIndex;

    while (leftPointer < rightPointer) {
        // 从最右边开始,直到找到小于中间点的位置
        while (leftPointer < rightPointer && array[rightPointer] >= pivot) {
            rightPointer--;
        }
        if (leftPointer < rightPointer) {
            // 第一次到这里时,会把第一次右边扫到的值,放到最左边的“坑”中,此时,最右边留下了“坑”
            array[leftPointer] = array[rightPointer];
            leftPointer++;
        }
        // 左边开始找,直到找到大于中间点的位置
        while (leftPointer < rightPointer && array[leftPointer] <= pivot) {
            leftPointer++;
        }
        if (leftPointer < rightPointer) {
            // 将这个大于中间点的位置的值放到上面右边留下的“坑”
            array[rightPointer] = array[leftPointer];
            rightPointer--;
        }
    }

    // 上面循环结束后,必然leftPointer = rightPointer,因为循环最后一步在这个重合位置留了“坑”,所以将中心点放进去
    array[rightPointer] = pivot;
    return rightPointer;
}
单指针
/**
 * 具体排序
 * 本方法采用 单指针
 *
 * @param array      待排数组
 * @param startIndex 开始下标
 * @param endIndex   结束下标
 * @return 中心点(pivot)下标
 */
private static int specificSort(int[] array, int startIndex, int endIndex) {
    // 将最左边的设置为中心点
    int pivot = array[startIndex];
    // 单指针从最左边开始
    int singlePointer = startIndex;
    // 遍历从开始位置的下一个开始,到最后位置结束
    for (int i = startIndex + 1; i <= endIndex; i++) {
        /*
         * 一旦遍历的位置的值小于中心点,则指针右移。
         * i是会大于等于singlePointer的,当array[i]的值大于中心点时,不会变,i会在循环后增加。
         * 所以当i>singlePointer时,singlePointer后面一位必然是大于中心点的。
         * 所以当i的位置的值小于中心点时,则可以和singlePointer后面一位的值交换。
         */
        if (array[i] < pivot) {
            singlePointer++;
            if (i != singlePointer) {
                int temp = array[singlePointer];
                array[singlePointer] = array[i];
                array[i] = temp;
            }
        }
    }

    // 一轮循环后,将中心点与最后的singlePointer位置交换,能保证singlePointer之后的值都是大于中心点的,同时,左边都是小于中心点的
    array[startIndex] = array[singlePointer];
    array[singlePointer] = pivot;
    return singlePointer;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值