八大排序之快速排序

一、基本思想

  快速排序是 一种基于交换的排序算法,是对冒泡排序的改进。它的基本思想是,通过一趟快速排序,将待排记录分割成独立的两部分,其中一部分的关键字均比另一部分小;在分别对这两部分进行排序排序,直至整个序列有序。 

二、操作步骤

  

  1.将待排记录分隔成独立的两部分,其中一部分的关键字均比另一部分小。选取第一个元素的关键字为支点,即进一次快速排序后,支点左边的元素的关键字均不大于支点的关键字,支点右边的元素的关键字不小于支点的关键字。将这部分操作封装成一个函数。

    1).用一个临时变量储存支点,这样,就有一个空位在左边,即支点的位置,用以存放从右侧选取的小于支点的元素。

    2).从右边开始,寻找比支点大的元素,找到之后将其放到左边的空位上,这样,空位就到右边了,用以存放从左侧选取的大于支点的元素。

    3).从左边开始,寻找比支点小的元素,找到之后将其放到右边的空位上,这样,空位就到了左边,用以存放从右侧选取的小于支点的元素。

    4).重复2)3)操作,知道整个记录遍历。最后将支点放回到空位上。

    进行上述操作后,待排记录就分割成了满足条件的两部分,支点也移动到了合适的位置。

  2.分别对上述两部分继续分割直至区间为一。这是一个递归的过程。

    

三、实现代码

  测试工具类 点击这里

package sort;

import sort.util.*;

/*
    快速排序思路:
    1.以某个元素为支点,改变支点位置,使得支点左边的值都不大于它,右边的值都不小于它
    2.对以支点划分的两个区间进行上述操作,直到区间长度为0
    
    时间复杂度:O(nlog2(n)),在数组基本有序时退化为O(n2)
    空间复杂度:O(log2(n)),递归需要栈空间
    稳定性:    不稳定,跳跃式移动
*/
public class QuickSort implements ISort {
    
    //划分,默认以a[left]为支点,返回划分后支点的位置
    private int partition(int[] a , int left , int right) {
        int t = a[left];                                  
        while(left < right) {                                      //挖坑填数法
            while(left < right && a[right] >= t) {right--;}        //一开始,坑在a[left],所以先找右边符合条件的数来填
            if(left < right) {a[left++] = a[right];}                 //填坑a[left] ,现在坑在a[right]了
            while(left < right && a[left] <= t) {left++;}          
            if(left <right){a[right--] = a[left];}
        } 
        a[left] = t;
        return left;
    }
    
    //递归调用划分,直到区间长度为0
    private void quicksort(int[] a , int left , int right) {       
        if(left < right){
            int dividePoint = this.partition(a , left , right);
            quicksort(a , left , dividePoint - 1);
            quicksort(a , dividePoint + 1 , right);
        }
    }
    
     //便于统一接口回调 
    public void sort(int[] a) {                                  
        this.quicksort(a , 0 , a.length - 1);
    }
    
    public static void main(String[] args) {
        int[] array = RandomArrayGenerator.getRandomArray(100 , 30);
        SortTestHelper.test(new QuickSort() , array);
    }
    
}

 测试结果:

四、总结分析

   时间复杂度:O(nlog n ),当待排记录有序时会退化为O(n2)

   空间复杂度:O(1)

   快速排序综合而言是比较优秀的排序算法,但由于跳跃式的记录交换,导致不稳定。

原文地址:https://www.cnblogs.com/wanghang-learning/p/9197865.html