快速排序

来源:互联网 发布:数据库前置机 编辑:程序博客网 时间:2024/05/17 22:46

思想:
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

实现步骤:
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个元素要O(nlogn)次比较。在最坏状况下则需要O(n^2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他O(nlogn)算法更快,因为它的内部循环可以在大部分的架构上很有效率地被实现出来。

  快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为:

从序列中挑出一个元素,作为"基准"(pivot).把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。对每个分区递归地进行步骤1~3,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。

宏观实现图:
这里写图片描述

  快速排序是不稳定的排序算法,不稳定发生在基准元素与A[tail+1]交换的时刻。

  比如序列:{ 1, 3, 4, 2, 8, 9, 8, 7, 5 },基准元素是5,一次划分操作后5要和第一个8进行交换,从而改变了两个元素8的相对次序。

代码:

package com.xujd.suanfa;import org.junit.Test;import com.xujd.util.TextUtil;// 分类 ------------ 内部比较排序// 数据结构 --------- 数组// 最差时间复杂度 ---- 每次选取的基准都是最大的元素(或者每次都是最小),导致每次只划分出了一个子序列,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2)// 最优时间复杂度 ---- 每次选取的基准都能使划分均匀,只需要logn次划分就能结束递归,时间复杂度为O(nlogn)// 平均时间复杂度 ---- O(nlogn)// 所需辅助空间 ------ O(logn)~O(n),主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度//  一般为O(logn),最差为O(n)(基本有序的情况)// 稳定性 ---------- 不稳定public class QuickSort {    int a[]={6,5,8,3,2,4,1,7};    int k=0;    int low=0;    int high=a.length-1;    @Test    public void quickSortA(){        quickSort(a,0,high);         TextUtil.print(a);        System.out.println(k);    }    public void quickSort(int[] a,int low, int high){        if(low<high){ //如果不加这个判断递归会无法退出导致堆栈溢出异常              int middle=getMiddle(a,low,high); //获取基准元素的位置             k++;            quickSort(a,  0,  middle-1);          //递归对低子表递归排序                quickSort(a,  middle + 1, high);        //递归对高子表递归排序           }     }    private int getMiddle(int[] a, int low, int high) {        int base = a[low];//基准元素,排序中会空出来一个位置          while(low<high){              while(low<high && a[high]>=base){//从high开始找比基准小的,与low换位置                  high--;              }              a[low]=a[high];              while(low<high && a[low]<=base){//从low开始找比基准大,放到之前high空出来的位置上                  low++;              }              a[high]=a[low];          }          a[low]=base;//此时low=high 是基准元素的位置,也是空出来的那个位置          return low;      }}