快排Java代码实现(Quick Sort)
  anLrwkgbyYZS 2023年12月30日 20 0


1.  快排算法思路

基本思想:通过一趟快速排序将待排数组分割成独立的两份部分; 其中一部分数组的值均比另一部分数组的值小,则可分别对着两部分数组继续进行排序,以达到整个序列有序。

快排的平均时间复杂度为n*log(n),最坏的时间复杂度为 n^2。

一趟快速排序:首先先选一个值(通常选择数组第一个值)作为枢轴,然后按下述原则重新排列其余的值,将数组中所有小于枢轴的值放在枢轴前面,数组中所有大于枢轴的值放在枢轴后面。将枢纽最后的位置作为分界线,将数组分成两部分(两部分均不包含枢轴),这个过程称作一趟快速排序。

一趟快速排序的具体做法

1.  设两个指针 low 和 high , 他们的初始值分别为数组开始的下标 start,数组结束的下标end

2.  枢轴值为 pivotKey

3.   则首先从 high 所指位置向前搜索,搜索到第一个小于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换。

4.  从 low 所指位置向后搜索,搜索到第一个大于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换。

5.  重复前两步操作(3,4),直至 low == high 。

2.  Java 代码实现

完全按照上面的思路的 Java 代码如下:

package sort;

/**
 * 快速排序(Quick Sort) Java代码实现
 * 快排时间复杂度:n*log(n)
 */

public class MySort {

    public static void main(String args[]) {
        int[] arr = new int[]{49, 38, 65, 97, 76, 13, 27};
        MySort mySort = new MySort();

        System.out.print("排序前的数组: ");
        PrintArray(arr, 0, arr.length-1);
        mySort.quickSort(arr, 0, arr.length-1);

        System.out.print("排序后的结果: ");
        PrintArray(arr, 0, arr.length-1);
    }

    /**
     * 对数组 arr 下标从 start 到 end 的内容进行排序
     * @param arr:待排序数组
     * @param start:开始的下标
     * @param end:结束的下标
     */
    public static void quickSort(int[] arr, int start, int end) {
        if(start >= end) {
            return;
        }

        // 1.  设两个指针 low 和 high ,他们的初始值分别为数组开始的下标 start,数组结束的下标end
        int low = start;
        int high = end;

        // 2.  枢轴值为 pivotKey
        int pivotKey = arr[start];

        // 5. 重复前两步操作(3,4),直至 low == high
        while (low<high) {

            // 3. 首先从 high 所指位置向前搜索,搜索到第一个小于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换
            while (low<high && arr[high]>=pivotKey) {
                --high;
            }
            int temp1 = arr[low];
            arr[low] = arr[high];
            arr[high] = temp1;


            // 4. 从 low 所指位置向后搜索,搜索到第一个大于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换。
            while (low<high && arr[low]<=pivotKey) {
                ++low;
            }
            temp1 = arr[low];
            arr[low] = arr[high];
            arr[high] = temp1;
        }

        // 对 小于枢轴值的那部分数组值 进行快排
        quickSort(arr, start, low-1);
        // 对 大于枢轴值的那部分数组值 进行快排
        quickSort(arr, low+1, end);
    }

    /**
     *输出数组中的值
     * @param arr:数组
     * @param start:数组开始的下标
     * @param end:数组结束的下标
     */
    public static void PrintArray(int[] arr, int start, int end) {

        for (int i=start; i<=end; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println("");
    }
}

运行可得 :

                      

快排Java代码实现(Quick Sort)_快排

3.  简单的优化

进行一次数值交换,如 :temp1 = arr[low]; arr[low] = arr[high]; arr[high] = temp1,需要三次赋值,temp1 = arr[low]; arr[high] = temp1 这两次赋值其实是多余的,因为 当 low == high , 也就是最终的位置 low ,就是枢轴值的位置,我们只需要在一次快排结束后将枢轴值放到 low 位置就可以了。Java源码如下。

package sort;

/**
 * 快速排序(Quick Sort) Java代码实现
 * 快排时间复杂度:n*log(n)
 */

public class MySort {

    public static void main(String args[]) {
        int[] arr = new int[]{49, 38, 65, 97, 76, 13, 27};
        MySort mySort = new MySort();

        System.out.print("排序前的数组: ");
        PrintArray(arr, 0, arr.length-1);
        mySort.quickSort(arr, 0, arr.length-1);

        System.out.print("排序后的结果: ");
        PrintArray(arr, 0, arr.length-1);
    }

    /**
     * 对数组 arr 下标从 start 到 end 的内容进行排序
     * @param arr:待排序数组
     * @param start:开始的下标
     * @param end:结束的下标
     */
    public static void quickSort(int[] arr, int start, int end) {
        if(start >= end) {
            return;
        }

        // 1.  设两个指针 low 和 high ,他们的初始值分别为数组开始的下标 start,数组结束的下标end
        int low = start;
        int high = end;

        // 2.  枢轴值为 pivotKey
        int pivotKey = arr[start];

        // 5. 重复前两步操作(3,4),直至 low == high
        while (low<high) {

            // 3. 首先从 high 所指位置向前搜索,搜索到第一个小于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换
            while (low<high && arr[high]>=pivotKey) {
                --high;
            }
            arr[low] = arr[high];


            // 4. 从 low 所指位置向后搜索,搜索到第一个大于 pivotKey 的 值,然后将这个值和  pivotKey 互相交换。
            while (low<high && arr[low]<=pivotKey) {
                ++low;
            }
            arr[high] = arr[low];
        }

        // 一次快排结束后将枢轴值放到 low 位置
        arr[low] = pivotKey;

        // 对 小于枢轴值的那部分数组值 进行快排
        quickSort(arr, start, low-1);
        // 对 大于枢轴值的那部分数组值 进行快排
        quickSort(arr, low+1, end);
    }

    /**
     *输出数组中的值
     * @param arr:数组
     * @param start:数组开始的下标
     * @param end:数组结束的下标
     */
    public static void PrintArray(int[] arr, int start, int end) {

        for (int i=start; i<=end; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println("");
    }
}

运行截图 :

快排Java代码实现(Quick Sort)_搜索_02

4.  优化措施

优化最坏的情况:在选择枢轴,取数组的第一个元素、中间的那个元素、最后一个元素的中位数作为枢轴。

优化最好的情况:添加两个 布尔类型 变量,如果 指针low 从低端向中间的移动过程中没有交换记录,则不需要对枢轴左部分的元素排序;如果 指针high 从高端向中间的移动过程中没有交换记录,则不需要对枢轴右部分的元素排序,这样就可能达到n的时间复杂度。

5.  参考文献

数据结构 -  严蔚敏、吴伟民 -  清华大学出版社

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

推荐阅读
anLrwkgbyYZS