zoukankan      html  css  js  c++  java
  • 排序算法3——快速排序

    算法复杂度:O(nlogn)

    原理

    对于一组给定的记录,通过一趟排序后,将原序列分为两部分,其中一部分的所有记录均比后一部分的所有记录小,然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中的所有记录均有序为止。

    程序

     1 public class quicksort {
     2 
     3     public static void quickSort(int array[],int low,int high){
     4         int pivot;
     5         if(low<high){
     6             pivot = partition(array,low,high);
     7             quickSort(array,low,pivot-1);
     8             quickSort(array,pivot+1,high);
     9         }
    10     }
    11 
    12 
    13     public static int partition(int array[],int low,int high){
    14         int index = array[low];
    15         while(low<high){
    16             while(low<high&&array[high]>=index)
    17                 high--;
    18             array[low] = array[high];
    19             while(low<high&&array[low]<index)
    20                 low++;
    21             array[high] = array[low];
    22         }
    23         array[low] = index;
    24         return low;
    25     }
    26     
    27 
    28     public static void main(String[] args){
    29         int a[] = {5,4,9,8,7,6,0,1,3,2};
    30         int len = a.length;
    31         quickSort(a,0,len-1);
    32         for(int i=0;i<len;i++){
    33             System.out.println(a[i]+" ");
    34         }
    35     }
    36 
    37 }

    优化

    1.优化选取枢轴

      采取三数取中法。取三个关键字先进性排序,将中间数作为枢轴,一般是取左端、右端和中间三个数,也可以随机选取。这样至少这个中间数一定不会是最小或最大的数,从概率来说,取三个数均为最小或最大数的可能性微乎其微,因此中间数位于较为中间的值的肯能行就大大提高了。

    将上面程序中的第14行改为如下程序

     1 int index;
     2 int m = low + (high - low) / 2;        //中间元素下标
     3 if(array[low]>array[high])
     4     swap(array,low,high);            //交换左端与右端数据,保证左端较小。
     5 if(array[m]>array[high])
     6     swap(array,m,high);                //交换中间与右端数据,保证中间较小。
     7 if(array[m]>array[low])
     8     swap(array,low,m);                //交换中间与左端数据,保证左端较小。
     9 /*此时array[low]已经是整个序列左中右三个关键字中的中间值。*/
    10 index = array[low];

    2.优化小数组时的排序方案

      当数组非常小时,快速排序反而不如直接插入排序来得更好。我们可以设置一个数组长度阈值(有资料认为7比较合适,也有认为50更合适,实际应用可适当调整),当数组长度在设定阈值之下时,就用直接插入排序,否则用快速排序。

    3.优化递归操作

      我们知道递归对性能是有一定的影响的,quickSort方法在其尾部有两次递归操作,如果待排序的序列划分极不平衡,递归深度将趋于n,这就不仅仅是速度快慢的问题了。栈的大小是很有限的,每次递归都会耗费一定的栈空间,函数的参数越多,每次递归耗费的空间也越多。如果能减少递归,将会大大提高性能。

    我们采取尾递归优化。

    将程序中的5-9行改为如下程序

    1 while(low<high){
    2     pivot = partition(array,low,high);
    3     quickSort(array,low,pivot-1);
    4     low = pivot+1;
    5 }

    常见排序算法的特点和比较

    排序法   平均时间     最好情形      最差情形 稳定度 额外空间 备注
    冒泡  O(n2) O(n)   O(n2)  稳定 O(1) n小时较好
    选择  O(n2) O(n2)  O(n2) 不稳定 O(1) n小时较好
    插入  O(n2) O(n)  O(n2) 稳定 O(1) 大部分已排序时较好
    Shell O(nlogn) O(n1.3) O(ns) 1<s<2 不稳定 O(1) s是所选分组
    O(nlogn) O(nlogn) O(nlogn) 不稳定 O(1) n大时较好
    归并 O(nlogn) O(nlogn) O(nlogn) 稳定 O(n) n大时较好
    快速 O(nlogn) O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好

  • 相关阅读:
    大型高性能ASP.NET系统架构设计
    读写锁ReaderWriterLockSlim
    日常生活英语单词大全
    unity3d读取plist或xml文件
    WIN7开无线
    asp.net 2.0中新增的web.config的默认namespace功能 (转)
    面向对象的一些基本概念
    大话设计模式之策略模式
    大话设计模式之简单的工厂模式
    iOS UI 之UILable
  • 原文地址:https://www.cnblogs.com/Eason-S/p/5490303.html
Copyright © 2011-2022 走看看