`
flyingdutchman
  • 浏览: 353345 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

快速排序及改进

阅读更多
        在初等的基本排序算法中,插入排序、归并排序和快速排序是常用的排序算法,实现简单,但很高效,它在空间复杂度和时间复杂度之前取得了最佳的平衡,这也是在现实工作中最常用的原因。
        下面是一些基本排序算法的比较:

                                                            几种常用的排序算法的比较
        快速排序算法是基于“分治算法”的排序算法,其基本思路是:将待排序的集合数组取一个元素叫基数,将其分成2个子数组,是基数左边的数都不大于该基数,而右边的数都不小于该基数;然后递归这一分解过程,并对子数组排序,而当所有的子数组都有序时,整个数组也就自然有序了。
        快速排序算法也是一个脆弱的排序算法,在对一个基本有序或已排序的数组做反向排序时,该算法会得到最坏时间复杂度——O(N*N),最好的时间复杂度为NlogN,平均时间复杂度接近于最好的时间复杂度NlogN,其空间复杂度为lgN。
        为了使快速排序获得最好的排序性能,最好在排序之前将之做一次“shuffle(洗牌)”操作,将原有顺序打乱之后再排序。
        快速排序的整个代码如下:
 /**
 * 排序的基类
 * @author jacky
 *
 */
 public class SortBase{
	
	  /**
	   * 将数组a中的数据顺序打乱
	   * @param a
	   */
    public static void shuffle(Comparable[] a) {
       int N = a.length;
       int r = 0;
       for (int i = 0; i < N; i++) {
           r = i + (int) (Math.random() * (N-i));
           exch(a, i, r);
       }
    }
	
	  /*
	   * 将a[i]和a[j]交换顺序
	   */
    public static void exch(Comparable[] a, int i, int j) {
       Comparable swap = a[i];
       a[i] = a[j];
       a[j] = swap;
    }
	
	   /**
	     * 判断v1是否小于v2
	     * @param v1
	     * @param v2
	     * @return true:小于;false:不小于
	    */
     public static boolean less(Comparable v1,Comparable v2){
	       return v1.compareTo(v1) < 0;
     }
 }    
  
 public class QuickSort extends SortBase{
    
	    public static void sort(Comparable[] a){
		   //为获得接近于最好的排序性能(最好的时间复杂度),首先将原数组“洗牌"
		   shuffle(a);
		   //开始排序
		   sort(a,0,a.length - 1);
	    }
	
	    /**
	     * 递归调用排序子数组
	     * @param a 
	     * @param lo
	     * @param hi
	     */
	     private static void sort(Comparable[] a,int lo,int hi){
		     if(hi <= lo) return;
		     //获取一个数组中的取快速切分的基数的下标,使其左边的元素不大于该数,
		     //其右边的元素不小于该数
		     int j = partition(a,lo,hi);
		     //将左半部分a[lo,j - 1]排序
		     sort(a,lo,j - 1);
		     //将右半部分a[就+ 1,hi]排序
		     sort(a,j + 1,hi);
	     }
	
	     /**
	      * 在数组a的小下标lo和hi范围内获取快速切分的基数的小标,使该基数的左边的
	      * 元素都不大于该数,而右边的元素都不小于该数
	      * @param a
	      * @param lo
	      * @param hi
	      * @return 快速切分基数的下标
	      */
	      public static int partition(Comparable[] a,int lo,int hi){
		     //将数组切分为a[lo...i - 1],a[i],a[j + 1,hi]
		     int i = lo,j = hi + 1;   //设置左右扫描指针
		     Comparable v = a[lo];    //切分元素
		     while(true){
			   while(less(a[++i],v)){
			 	if(i == hi) break;
			   }
			   while(less(v,a[--j])){
				if(j == lo) break;
			   }
			   if(i >= j){
				break;
			   }
			   exch(a,i,j);  
		     }
		     exch(a,lo,j); //将v = a[i]放入正确的位置
		     //a[lo...j - 1] <= a[j] <= a[j + 1 ... hi]
		     return j; 
	      }
 }
  

        快速排序与归并排序相比,一般情况下速度要快于归并排序,但是对于小数组,其排序速度要较插入排序慢一些。对于在给小数组排序时,快速排序的排序速度要较插入排序慢这一特点,我们可以对快速排序算法做如下改进:
public class QuickSort extends SortBase{
    
	    public static void sort(Comparable[] a){
		   //为获得接近于最好的排序性能(最好的时间复杂度),首先将原数组“洗牌"
		   shuffle(a);
		   //开始排序
		   sort(a,0,a.length - 1);
	    }
	
	    /**
	     * 递归调用排序子数组
	     * @param a 
	     * @param lo
	     * @param hi
	     */
	     private static void sort(Comparable[] a,int lo,int hi){
		     //改进处:由插入排序替换该行代码if(hi <= lo) return;
                     if(hi <= lo + M){//M取5-15之间的值是比较不错的选择
                         //插入快速排序的代码如:
                         InsertSort.sort(a,lo,hi);//代码自己实现
                         return;
                     }

		     //获取一个数组中的取快速切分的基数的下标,使其左边的元素不大于该数,
		     //其右边的元素不小于该数
		     int j = partition(a,lo,hi);
		     //将左半部分a[lo,j - 1]排序
		     sort(a,lo,j - 1);
		     //将右半部分a[就+ 1,hi]排序
		     sort(a,j + 1,hi);
	     }
	
	     /**
	      * 在数组a的小下标lo和hi范围内获取快速切分的基数的小标,使该基数的左边的
	      * 元素都不大于该数,而右边的元素都不小于该数
	      * @param a
	      * @param lo
	      * @param hi
	      * @return 快速切分基数的下标
	      */
	      public static int partition(Comparable[] a,int lo,int hi){
		     //将数组切分为a[lo...i - 1],a[i],a[j + 1,hi]
		     int i = lo,j = hi + 1;   //设置左右扫描指针
		     Comparable v = a[lo];    //切分元素
		     while(true){
			   while(less(a[++i],v)){
			 	if(i == hi) break;
			   }
			   while(less(v,a[--j])){
				if(j == lo) break;
			   }
			   if(i >= j){
				break;
			   }
			   exch(a,i,j);  
		     }
		     exch(a,lo,j); //将v = a[i]放入正确的位置
		     //a[lo...j - 1] <= a[j] <= a[j + 1 ... hi]
		     return j; 
	      }
 }
       
  • 大小: 58.8 KB
分享到:
评论

相关推荐

    快速排序的改进算法

    快速排序的改进算法,经典推荐

    快速排序法改进版

    在快速排序法基础上提供了一些改进,比基本的快速排序更方便简洁

    论文研究-一种三路划分快速排序的改进算法.pdf

    针对快速排序在某些特殊情况下如数据已有序或重复数据较多时效率较低的问题进行了研究, 对三路快速排序进行改进, 使快速排序在特殊情况下也能保持较好的效率。通过大量的数据测试发现, 该算法在最好情况下其性能在几...

    从最简单快速排序到各种改进的算法

    这是简单的快速排序和加入各种改进算法的后的代码都有,比如快排入栈操作等

    改进的快速排序算法

    快速排序算法的改进思路 1.选取好的基准,是两边的数据个数尽量的均匀 取数组的第一个,中间,最后一个数据,取三个数中第二大的数作为基准 2. 不递归 3.与插入结合,当段内的数组个数小于等于16的时候,使用...

    快速排序的改进算法(和插入排序结合)

    快速排序用的主要是partition函数,在此程序里,快速排序改进,在调用partition将数组进行分组的时候,当子数组个数小于k时,不继续做快速排序,直接返回,k由用户自己定义大小。将返回的基本有序的数组进行插入排序...

    改进的快速排序

    为快速排序的算法及程序实现。其它的就没有什么了。

    快速排序的基本算法和改进实现

    快速排序算法改进--小的子文件、三者取中、重复关键字三路划分

    快速排序的两种改进方法

    本资源包含快排(Quicksort)桶排序(BucketSort)三数取中快速排序(middle、partition、QuickSort3)及三数取中+同key值相聚快速排序(middle1、QuickSort4)。可见三数取中+同key相聚算法还是很猛的!

    快速排序-改进的枢轴元素-三者取中算法比较

    输入若干组长度各异的待排序列,分别用快速排序算法和改进的枢轴元素三者取中算法对待排序列进行排序,当待排子序列长度已小于 20时,改用直接插入排序,利用时间函数验证三者取中算法在效率上的提高。(提示: 待排...

    快速排序改进(取首尾平均值做枢轴)

    取首尾元素的值的平均值作为比较,是快速排序的改进算法

    快速排序的改进算法,时间复杂度的详细解答

    最好情况下, 最坏情况下, 平均情况下的时间复杂度

    快速排序的改进型1

    快速排序的改进型:对于从1到1千万中的1百万个随机整数排序,其结果如下:对比java自带的Arrays.sort()的速度还要提升3倍,其原因应该是在于多一个监

    快速排序及其改进方法的c++ 代码 quicksort.cpp

    代码中包含了快速排序这个经典算法的代码,并且给出了改进后的快速排序的代码,代码中同时包含了两个测试用例。测试命令:g++ quicksort.cpp -o quicksort ./quicksork

    C语言实现快速排序算法

    快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此...

    快速排序实现算法(c)

    快速排序是对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个...

    快速排序,冒泡排序,插入排序,选择排序的四种算法

    有一个模板类写出了快速排序,冒泡排序,插入排序,选择排序四种算法。用的是C++哦

    排序算法C语言版:快速排序

    快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟 扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次 扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只 减少1。快速...

    浅析C语言快速排序算法的改进.pdf

    浅析C语言快速排序算法的改进

    使用改进的快速排序查找多目标帕累托前沿(matlab)

    使用改进的快速排序查找多目标帕累托前沿 此函数返回给定多目标解空间的帕累托最优设计集的索引 此函数将索引返回到对应于帕累托最优设计集的给定矩阵。该函数的底层算法基于快速排序,并且对于具有有利的领先系数的...

Global site tag (gtag.js) - Google Analytics