zoukankan      html  css  js  c++  java
  • 快速排序

    速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。

    总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定。

    快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

    该方法的基本思想是:

    1.先从数列中取出一个数作为基准数。

    2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

    3.再对左右区间重复第二步,直到各区间只有一个数。

    虽然快速排序称为分治法,但分治法这三个字显然无法很好的概括快速排序的全部步骤。因此我的对快速排序作了进一步的说明:挖坑填数+分治法:

    import java.util.Arrays;
    
    /**
     * 第1次排序:[9, 6, 12, 34, 45, 79, 65]
     * 第2次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第3次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第4次排序:[6, 9, 12, 34, 45, 65, 79]
     */
    public class QuickSort {
        public static int count = 0;
    
        public static void main(String[] args) {
            int array[] = {34, 65, 12, 45, 6, 79, 9};
            quickSort(array);
        }
    
        public static void quickSort(int[] array) {
            if (array != null) {
                quickSort(array, 0, array.length - 1);
            }
        }
    
        private static void quickSort(int[] array, int beg, int end) {
            if (beg >= end || array == null)
                return;
            int p = partition(array, beg, end);
    //        System.out.println("第一次排序");
            System.out.print("第" + (++count) + "次排序:");
            System.out.print(Arrays.toString(array));
            System.out.println();
            quickSort(array, beg, p - 1);
            quickSort(array, p + 1, end);
        }
    
        private static int partition(int[] array, int beg, int end) {
            int pivot = array[beg];
            while (beg < end) {
                while (beg < end && array[end] >= pivot)
                    end--;
                if (beg < end)
                    array[beg++] = array[end];
                while (beg < end && array[beg] <= pivot)
                    beg++;
                if (beg < end)
                    array[end--] = array[beg];
            }
            array[beg] = pivot;
            return beg;
        }
    
    }
    //  快排空间复杂度O(log2(n))   归并O(n)    
    //
    //        心情不稳当,快些选一对好友来聊天-----------快速,希尔,简单选择,堆排序---------------不稳当
    //
    //          快些以 nlog2(n)归队------------------------快速,希尔,归并,堆排序----------------------时间负载度 nlog2(n)
    //
    //          
    //
    //          直接插容易插成O(n),起泡起的好编程O(n)------------------容易插,起的好,都是初始化序列已经有序

    下面以中间为基排序

    这个时候要注意,比较条件是大于或者小于,不能有等于,不然程序会出错

    import java.util.Arrays;
    import java.util.Comparator;
    
    
    /**
     * 快速排序。
     * <p>
     * 第1次排序:[34, 9, 12, 6, 45, 79, 65]
     * 第2次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第3次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第4次排序:[6, 9, 12, 34, 45, 65, 79]
     * 第5次排序:[6, 9, 12, 34, 45, 65, 79]
     * 最终结果
     * [6, 9, 12, 34, 45, 65, 79]
     */
    
    /**
     * 第1次排序:[34, 9, 12, 6, 45, 79, 65]
     * 第2次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第3次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第4次排序:[6, 9, 12, 34, 45, 65, 79]
     * 第5次排序:[6, 9, 12, 34, 45, 65, 79]
     * 最终结果
     * [6, 9, 12, 34, 45, 65, 79]
     */
    
    /**
     * 分治和递归,以中间为准基数,分割数组为两部分,
     *      如果左边的index0指向数据小于准基数,则满足条件(左边的小于准基数),
     *      下标增加一(index0++),用下一个数据和准基数对比,如果满足,再看一下个数据。
     *      如果右边的数据大于准基数,则满足条件(右边的数据大于准基数),
     *      下边减一(index1--),用上一个数据和准基数进行对比。。。
     */
    
    public class QuickSort2 {
        public static int count = 0;
    
        public static void QuickSort2(int[] inputs, Comparator<Integer> cp) {
    
            sort(inputs, 0, inputs.length - 1, cp);
        }
    
        /**
         * 快速排序算法,结果是从小到大。
         *
         * @param inputs 待排序对象数组。
         * @param low    首
         * @param high   尾
         */
        private static void sort(int[] inputs, int low, int high,
                                 Comparator<Integer> cp) {
            int index0 = low;
            int index1 = high;
            int mid;
            if (high > low) {
                mid = inputs[(low + high) / 2];
                while (index0 <= index1) {
                    while ((index0 < high) && (cp.compare(inputs[index0], mid) < 0)) {
                        ++index0;
                    }
                    while ((index1 > low) && (cp.compare(inputs[index1], mid) > 0)) {
                        --index1;
                    }
                    if (index0 <= index1) {
                        swap(inputs, index0, index1);
                        ++index0;
                        --index1;
                    }
                }
                System.out.print("第" + (++count) + "次排序:");
                System.out.print(Arrays.toString(inputs));
                System.out.println();
                if (low < index1) {
                    sort(inputs, low, index1, cp);
                }
                if (index0 < high) {
                    sort(inputs, index0, high, cp);
                }
            }
        }
    
        /**
         * 交换。
         *
         * @param objs
         * @param i
         * @param j
         */
        private static void swap(int[] objs, int i, int j) {
            int T;
            T = objs[i];
            objs[i] = objs[j];
            objs[j] = T;
        }
    
        public static void main(String[] args) {
            int array[] = {34, 65, 12, 45, 6, 79, 9};
            Comparator<Integer> integerComparator = new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1 - o2;
                }
            };
            QuickSort2(array, integerComparator);
            System.out.println("最终结果");
            System.out.println(Arrays.toString(array));
    
    
        }
    }
    import java.util.Arrays;
    
    
    /**
     * 快速排序。
     * 第1次排序:[34, 9, 12, 6, 45, 79, 65]
     * 第2次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第3次排序:[6, 9, 12, 34, 45, 79, 65]
     * 第4次排序:[6, 9, 12, 34, 45, 65, 79]
     * 第5次排序:[6, 9, 12, 34, 45, 65, 79]
     * [6, 9, 12, 34, 45, 65, 79]
     */
    public class QuickSort3 {
        public static int count = 0;
    
        public static void QuickSort3(int[] inputs) {
            sort(inputs, 0, inputs.length - 1);
        }
    
        /**
         * 快速排序算法,结果是从小到大。
         *
         * @param inputs 待排序对象数组。
         * @param low    首
         * @param high   尾
         */
        private static void sort(int[] inputs, int low, int high) {
            int index0 = low;
            int index1 = high;
            int mid;
            if(count==3){
                System.out.println(111);
            }
            if (high > low) {
                mid = inputs[(low + high) / 2];
                while (index0 <= index1) {
                    while ((index0 < high) && ((inputs[index0] - mid) < 0)) {
                        ++index0;
                    }
                    while ((index1 > low) && ((inputs[index1] - mid) > 0)) {
                        --index1;
                    }
                    if (index0 <= index1) {
                        swap(inputs, index0, index1);
                        ++index0;
                        --index1;
                    }
                }
                System.out.print("第" + (++count) + "次排序:");
    
                System.out.print(Arrays.toString(inputs));
                System.out.println();
                if (low < index1) {
                    sort(inputs, low, index1);
                }
                if (index0 < high) {
                    sort(inputs, index0, high);
                }
            }
        }
    
        /**
         * 交换。
         *
         * @param objs
         * @param i
         * @param j
         */
        private static void swap(int[] objs, int i, int j) {
            int T;
            T = objs[i];
            objs[i] = objs[j];
            objs[j] = T;
        }
    
        public static void main(String[] args) {
            int array[] = {34, 65, 12, 45, 6, 79, 9};
    
            QuickSort3(array);
            System.out.println(Arrays.toString(array));
    
        }
    }


    这个问题其实也没有多么复杂,但是网上这部分内容不多,故总结一下最优与最差比较次数。

    
    

    n个元素线性表快速排序,最好情况下比较次数是多少?

    
    

    参照严书的方法,以第一位作为标杆。

    
    

    ①考虑第一趟排序,无论怎样也要有n-1次比较次数;

    
    

    ②如果此时能把数据分成两部分,前一部分与后一部分元素个数相近,那样就是最优的。

    
    

      例如,4 1 2 3 5 6 7,经过一趟排序,变成 1 2 3 4 5 6 7 。也就是说,以4为标杆,一趟后分成了两部分,这两部分个数相同或相差  1,那么快排会很优。

    
    

      于是,可以想到,最优时,n个数,第一趟分成前⌊(n-1)/2⌋,后⌈(n-1)/2⌉两组,每组也是按照最优的分,设最优是an,于是有:

    
    

       an = a⌊(n-1/2)⌋+a⌈(n-1/2)⌉ + n - 1

    
    

      比如,n=7时,最优情况就是  a7=a3+a3+6 ,a3=a1+a1+2 ,而显然a1=0。 

    
    

       于是a3=2,a7=10。

    
    
    
    
    

       举 例  4 1 3 2 6 5 7 。第一次4为标杆,一趟后为 2 1 34 6 5 7 

    
    

       第二趟两边分别以2,6为标杆,这样最好,因为是均分了。

    
    

       问题,n=8时,最好排序次数?

    
    

       a8=7+a4+a3,a3算的2,a4=3+a1+a2,显然a2=1,于是a4=4,故a8=13

    
    

       因此,n=8时,最好情况下比较次数是13。

    
    

      举例,4 1 3 2 6 5 7 8  可以数一下

    
    

       对于别的情况,参照这个思路即可轻松求比较次数以及举例。

    
    
    
    
    

    n个元素线性表快速排序,最坏情况下比较次数是多少?

    
    

        这个就容易多了,因为顺序或者逆序时最坏的。

    
    

        故比较次数,1+2+3……+ n-1 = n(n-1)/2

     
  • 相关阅读:
    JDK8 Optional类使用
    Kafka RocketMQ
    Dubbo,ElasticSearch,JVM,多线程/高并发,消息中间件 常问问题
    Redis
    java jvm 虚拟机
    25 岁做什么,可在 5 年后受益匪浅?
    设计模式
    并发与并行的理解
    多线程学习
    FireFox 如何在当前页面打开书签
  • 原文地址:https://www.cnblogs.com/chengpeng15/p/9321295.html
Copyright © 2011-2022 走看看