• 排序算法之快速排序


    一、原理

    通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后在按此方法对这两部分数据分别进行排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列的过程。

    二、代码实现

    package com.jdk8.SortTest;
    
    public class QuickSort {
    
        public static void display(int[] arrays){
            for(int i = 0;i < arrays.length;i++){
                System.out.print(" " +  arrays[i] + " ");
            }
        }
    
        public static void main(String[] args){
            int[] arrays = {3,9,63,93,72,15,27,86};
            System.out.println("排序前的数据为:");
            display(arrays);
            doQuickSort(arrays,0,arrays.length-1);
            System.out.println();
            System.out.println("排序后的数据为:");
            display(arrays);
            System.out.println();
    
        }
    
        private static void doQuickSort(int[] arrays,int left,int right) {
            if(left >= right){
                return;
            }
            int index = partition(arrays,left,right);
            doQuickSort(arrays,left,index-1);
            doQuickSort(arrays,index+1,right);
        }
    
        private static int partition(int[] arrays, int left, int right) {
            int key = arrays[left];
            while(right > left){
                while(arrays[right] > key && right > left){
                    right = right - 1;
                }
                if(left != right){
                    arrays[left] = arrays[right];
                }
                while(arrays[left] <= key && left < right){
                    left = left + 1;
                }
                if(left != right){
                    arrays[right] = arrays[left];
                }
            }
            arrays[right] = key;
            return right;
        }
    
    }
    

    三、复杂度分析

    3.1、时间复杂度分析

    ​ 快速排序时间复杂度为n*lg(n) ,推导过程如下所示:

    f(n)来表示数据量为n时,算法的计算次数,很容易知道:
    - 当n=1时,quick_sort函数只计算1次
    f(1)=1【式子A】
    
    在n很大时:
    第一步,先做一次partition;
    第二步,左半区递归;
    第三步,右半区递归;
    即:
    f(n)=n+f(n/2)+f(n/2)=n+2*f(n/2)【式子B】
    画外音:
    (1)partition本质是一个for,计算次数是n;
    (2)二分查找只需要递归一个半区,而快速排序左半区和右半区都要递归,这一点在*分治法与减治法*一章节已经详细讲述过;
    
    【式子B】不断的展开,
    f(n)=n+2*f(n/2)
    f(n/2)=n/2+2*f(n/4)
    f(n/4)=n/4+2*f(n/8)
    …
    f(n/2^(m-1))=n/2^(m-1)+2f(n/2^m)
    
    上面共m个等式,逐步带入,于是得到
    
    f(n)=n+2*f(n/2)
    =n+2[n/2+2f(n/4)]=2n+4*f(n/4)
    =2n+4[n/4+2f(n/8)]=3n+8f(n/8)
    =…
    =mn+2^mf(n/2^m)
    
    再配合【式子A】:
    
    f(1)=1
    即,n/2^m=1时, f(n/2^m)=1, 此时m=lg(n), 这一步,这是分析这个算法的关键。
    将m=lg(n)带入,得到:
    
    f(n)=lg(n)n+2^(lg(n))f(1)=n*lg(n)+n
    
    故,快速排序的时间复杂度是n*lg(n)。
    
    

    3.2、空间复杂度

    ​ 快速排序的临时变量所占用的空间不随处理数据n的大小改变而改变,即空间复杂度为O(1)。

    四、稳定性

    ​ 快速排序是一个不稳定的排序

    ​ 例如(5,3A,6,3B)对这个进行排序,排序之前相同的数3A与3B,A在B的前面,经过排序之后会变成

    (3B,3A,5,6),所以说快速排序是一个不稳定的排序

  • 相关阅读:
    Hit Event 击中碰撞
    基于ReentrantLock通知唤醒的生产消费模式
    spring 源码构建
    读写分离、分库、分表
    python 反射的使用
    基础算法
    git 命令使用
    java设计模式应用
    linux 中python的使用
    linux命令
  • 原文地址:https://www.cnblogs.com/ITBlock/p/10398483.html
Copyright © 2020-2023  润新知