`
flyingdutchman
  • 浏览: 358459 次
  • 性别: 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
分享到:
评论

相关推荐

    快速排序的改进算法

    ### 快速排序的改进算法 #### 一、引言 快速排序是由C.A.R. Hoare于1962年提出的一种高效的排序算法。它以其优秀的平均性能和较小的常数因子,在实际应用中非常受欢迎。然而,在最坏情况下,快速排序的时间复杂度...

    快速排序法改进版

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

    改进的快速排序

    ### 改进的快速排序算法解析 #### 快速排序简介 快速排序是一种非常高效的排序算法,采用分治策略来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。该算法的基本思想是:选择一个基准元素...

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

    ### 快速排序改进算法:时间复杂度的深入解析 #### 快速排序的基本概念与问题 快速排序,由C.A.R.Hoare于1962年提出,是一种高效的排序算法,基于分治策略。它通过选择一个“基准”元素,将数据集分割成两个子集,...

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

    标题中的“从最简单快速排序到各种改进的算法”,指的是在理解了快速排序的基本原理后,对它进行优化以提高其性能。快速排序的平均时间复杂度为O(n log n),但在最坏的情况下,当输入数组已经部分或完全有序时,时间...

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

    现在,我们来看看几种快速排序的改进方法: 1. **处理小的子文件**:对于小规模的子文件,直接使用插入排序可能更有效,因为插入排序在数据量小时有较好的表现。当子文件大小低于某个阈值时,可以切换到插入排序。 ...

    改进的快速排序算法

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

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

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

    快速排序的改进型1

    在标题和描述中提到的“快速排序的改进型”,通常指的是在基础的快速排序算法上进行的一些优化,以提高性能。一种常见的优化策略是引入“监视哨”或“三向切分”的概念。监视哨的目的是减少不必要的交换操作,它会...

    快速排序的两种改进方法

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

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

    而本篇文章介绍的“快速排序改进(取首尾平均值做枢轴)”,则提供了一种新的枢轴选择策略,即取首尾元素的平均值作为比较基准,这种策略在一定程度上可以避免数据偏斜带来的问题,提高排序效率。 具体来说,改进后...

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

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

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

    "C语言快速排序算法的改进" 快速排序算法是计算机程序设计中的一种重要操作, 本文论述了C语言快速排序算法的改进,即快速排序与直接插入排序算法相结合的实现过程。在C语言程序设计中,实现大量的内部排序应用时,...

    快速排序算法相关分析

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

    快速排序算法的改进与分析.doc

    通过对快速排序的改进,可以有效地缓解这些缺点,使其在各种数据集上都能保持较高的性能。在实际应用中,快速排序通常与其他排序算法结合,形成更强大的排序工具,如在数据库系统和数据分析中广泛使用。

    快速排序算法及其改进算法的分析与评价.doc

    双倍快速排序是快速排序的一种改进,它尝试通过增加每次划分的元素数量来提高效率,例如,每次选取两个基准元素,然后进行分区操作。这种方法旨在减小最坏情况的发生概率,并可能提高在某些情况下的平均性能。 3.1 ...

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

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

    C语言实现快速排序算法

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

    7大排序算法实现程序(快速排序,冒泡排序,选择排序,归并排序,插入排序,希尔排序,堆排序)

    本资源提供了七大经典排序算法的实现程序,包括快速排序、冒泡排序、选择排序、归并排序、插入排序、希尔排序和堆排序。下面将逐一详细介绍这些排序算法及其原理。 1. 快速排序:由C.A.R. Hoare提出,是一种采用...

Global site tag (gtag.js) - Google Analytics