zoukankan      html  css  js  c++  java
  • 数组排序-快速排序(Quick Sort)


    概念:

        快速排序是对冒泡排序的一种改进。由C.A.R.Hoare于1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。


    排序过程:

        假设要排序的数组是A[0]..A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它的前面,所有比它大的数据都放到它的后面,这个过程称为一趟快速排序。值得注意的是:快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
        一趟快速排序的算法是:
        1.设置两个变量i、j,排序开始时:i=0; j=N-1;
        2.以第一个数组元素作为关键数据,赋值给key,即key=A[0];
        3.从j开始向前检索,即由后向前开始检索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
        4.从i开始向后检索,即由前向后开始检索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
        5.重复第3、4步,直到i=j;(3、4步中,没找到符合条件的值,即第3步中A[j]不小于key,第4步中A[i]不大于key时改变i、j的值,使得j=j-1; i=i+1; 直至找到该值为止。找到符合条件的值,进行交换的时候i和j的指针位置不变。另外,i==j这一过程一定正好是i++或j--完成的时候,此时令循环结束)


    示例:

    package com.cnblogs.lxj.testarraysort;
    
    /**
     * @author liuxiaojiang
     * @packageName:com.cnblogs.lxj.testarraysort
     * @ClassName:QuickSort
     * @Description:测试快速排序
     * @date 2020/11/30
     */
    public class QuickSort {
    
        /**
         * 主方法
         * @param args
         */
        public static void main(String[] args) {
            int[] a = {5,1,9,3,7,4,8,6,2};
            printArray(a);
            quickSort(0,a.length - 1,a);
            printArray(a);
        }
    
        /**
         * 快速排序方法
         * @param low
         * @param high
         * @param a
         */
        public static void quickSort(int low,int high,int[] a){
            if(low < high){
                int middle = getMiddle(low,high,a);
                quickSort(low,middle - 1,a);
                quickSort(middle + 1,high,a);
            }
        }
    
        /**
         * 逻辑算法
         * @param low
         * @param high
         * @param a
         * @return
         */
        public static int getMiddle(int low,int high,int[] a){
            int temp = a[low];
            while(low < high){
                while(a[high] >= temp && low < high){
                    high--;
                }
                a[low] = a[high];
                low++;
                while(a[low] <= temp && low < high){
                    low++;
                }
                a[high] = a[low];
            }
            a[high] = temp;
            return high;
        }
    
        /**
         * 输出方法
         * @param array
         */
        public static void printArray(int[] array){
            for(int a : array){
                System.out.print(a + " ");
            }
            System.out.println();
        }
        
    }
    
    

    运行结果:

    5 1 9 3 7 4 8 6 2      //初始化
    1 2 3 4 5 6 7 8 9      //快速排序完成
    

    原理:


    算法分析:

        快速排序可以说是数组排序中性能最好的排序算法,但它是不稳定的算法,比如当同一数组中有两个(或多个)值相同的元素时,排序完成后,该多个元素位置(顺序)可能会发生改变。快速排序主要有两个基本操作:一是选取枢轴元素,另一个则是递归分割数组。枢轴元素的选取对快速排序的效率至关重要,因为它决定了递归的深度。如果枢轴元素刚好处于数组的中间值,那么,数组在分割时就分成了平均的两部分。这样的递归的效率就好。如果每次选取的枢轴元素都是最大/最小 的那个元素,则快排复杂度达到了O(N2),而且还用了递归栈空间。快速排序的时间复杂度与枢轴元素的选取息息相关。平均情况下,时间复杂度为O(NlogN),最坏情况下为O(N2)。所以,快速排序更适合数据量比较大时使用。(另:需要注意,当选取数组元素中的最小值作为枢轴且要降序时,这时候的执行时间巨长,所以,在使用时需要根据实际情况调整)


  • 相关阅读:
    HDU 1261 字串数(排列组合)
    Codeforces 488C Fight the Monster
    HDU 1237 简单计算器
    POJ 2240 Arbitrage
    POJ 3660 Cow Contest
    POJ 1052 MPI Maelstrom
    POJ 3259 Wormholes
    POJ 3268 Silver Cow Party
    Codesforces 485D Maximum Value
    POJ 2253 Frogger(最短路)
  • 原文地址:https://www.cnblogs.com/joyfulcode/p/14061297.html
Copyright © 2011-2022 走看看