快速排序的主要优化

对于快排的优化大概有这样几点:

1、减少 swap 次数 或者 直接不用 swap 操作,从整体上考虑每次 (i, j)元素的交换,让每次元素对的交换变成整体上挪位:

 1 // 快排: 选定轴点
 2 int parti(int lo, int hi)
 3 {
 4     swap(num[lo], num[lo + rand() % (hi - lo + 1)]);
 5     int pivot = num[lo];
 6     while (lo < hi)
 7     {
 8         while ((lo < hi) && (pivot <= num[hi])) hi--;
 9         num[lo] = num[hi];
10         while ((lo < hi) && (num[lo] <= pivot)) lo++;
11         num[hi] = num[lo];
12     }
13     num[lo] = pivot;
14     return lo;
15 }

表现在有下划线的代码上。

2、对于轴点的选取,要使左右集合的规模尽可能相当。

  可以采取的方法有:随机选取法、三者取中法。

  相比而言,对于最坏情况产生的概率,三者取中法又比随机选取法更能有效避免。

3、对于退化情形的考虑,即重复元素。

  可以将上述选取轴点代码优化为:

 1 // 快排: 选定轴点
 2 int parti(int lo, int hi)
 3 {
 4     swap(num[lo], num[lo + rand() % (hi - lo + 1)]);
 5     int pivot = num[lo];
 6     while (lo < hi)
 7     {
 8         while (lo < hi)
 9       {
10           if (pivot < num[hi]) hi--;
11           else
12           {
13               num[lo++] = num[hi];
14               break;
15           }
16       }
17       while (lo < hi)
18       {
19           if (num[lo] < pivot)) lo++;
20           else
21           {
22               num[hi--] = num[lo];
23               break;
24           }
25       }
26     }
27     num[lo] = pivot;
28     return lo;
29 }

这样对于全部都是一样的元素,也能将轴点选取在中点位置而不会退化为最坏情况。代价是实际上的交换变多了。

From:我的知乎回答:http://www.zhihu.com/question/19841543/answer/46760856

时间: 2024-10-12 16:14:23

快速排序的主要优化的相关文章

&lt;算法笔记&gt;关于快速排序的算法优化排序(顺便给百度百科纠个错)

快速排序是排序算法之中的基本中的基本,虽然越来越多的接口函数将快速排序“完美的封装了起来”,比如C++中的qsort或者<algorithm>中的sort(与stable_sort相对应),但是深入思考,关于快速排序的优化你可曾想过?:-P (一)经典快速排序 首先我们来看一下这个百度百科之中的快速排序版本 在上面这张图中,我们一边纠错一边复习下基本的快速排序,基本快速排序的函数体可以明确分为三个块: 1.调整块,根据对称轴pivot(一般选取第一个)从数组的前后两端向中间扫描,pivot作对

快速排序分区以及优化方法

一.快速排序扫描分区法 通过单向扫描,双向扫描,以及三指针分区法分别实现快速排序算法.着重理解分区的思想. 单向扫描分区法 思路:用两个指针将数组划分为三个区间,扫描指针(scan_pos)左边是确认小于等于主元的,扫描指针到某个指针(next_bigger_pos)中间为未知的,因此我们将第二个指针(next_bigger_pos)称为未知区间指针,末指针的右边区间为确认大于主元的元素.主元就是具体的划分数组的元素,主元的选择有讲究,这里选择数组的首元素 代码: import java.uti

算法重拾之路——快速排序

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 第一章:分治与递归 快速排序 算法描述: 同合并排序一样,就是对于一堆数据进行排序. 快排的原理就是,找一个标准,以这个标准为中心进行扩展.就像以前 做操 的时候,老师会说,以XXX为基准,成体操队形散开,这时,XXX左右的人分别就会向它看齐,并向外扩散.快排原

Html5 快速排序演示

快速排序(Quicksort)是对冒泡排序的一种改进.快速排序由C. A. R. Hoare在1962年提出. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动. 每次尽可能地选择一个能够代表中值的元素作为关键数据,然后遵循普通快排的原则进

快速排序中的partition函数的枢纽元选择,代码细节,以及其标准实现

很多笔试面试都喜欢考察快排,叫你手写一个也不是啥事.我很早之前就学了这个,对快速排序的过程是很清楚的.但是最近自己尝试手写,发现之前对算法的细节把握不够精准,很多地方甚至只是大脑中的一个映像,而没有理解其真正的本质意图.于是今天结合了<数据结构>(严蔚敏),和<算法导论>进行一番探究. 首先先给出快速排序的严蔚敏版的实现(实际上这部分的partition也是算法导论里面思考题的实现方式,细节可能不一样): 1 public class QuickSort implements So

sort函数详解(史上最完整QAQ)

1.sort 使用:#include <algorithm>   using namespace std; 作用:排序 时间复杂度:n*lg(n) 实现原理:sort并不是简单的快速排序,它对普通的快速排序进行了优化,此外,它还结合了插入排序和推排序.系统会根据你的数据形式和数据量自动选择合适的排序方法,这并不是说它每次排序只选择一种方法,它是在一次完整排序中不同的情况选用不同方法,比如给一个数据量较大的数组排序,开始采用快速排序,分段递归,分段之后每一段的数据量达到一个较小值后它就不继续往下

线程 Z

原文:http://www.albahari.com/threading/part5.aspx 专题:C#中的多线程 1并行编程Permalink 在这一部分,我们讨论 Framework 4.0 加入的多线程 API,它们可以充分利用多核处理器. 并行 LINQ(Parallel LINQ)或称为 PLINQ Parallel类 任务并行(task parallelism)构造 SpinLock 和 SpinWait 这些 API 可以统称为 PFX(Parallel Framework,并行

C#中的多线程 - 并行编程 z

原文:http://www.albahari.com/threading/part5.aspx 专题:C#中的多线程 1并行编程Permalink 在这一部分,我们讨论 Framework 4.0 加入的多线程 API,它们可以充分利用多核处理器. 并行 LINQ(Parallel LINQ)或称为 PLINQ Parallel类 任务并行(task parallelism)构造 SpinLock 和 SpinWait 这些 API 可以统称为 PFX(Parallel Framework,并行

效能分析——词频统计1.1版

前言:在寻错及修改两天之后,发现之前的程序不能处理大文件的原因在于所写的排序部分,于是做了两件事: 第一是修改了所写的quick排序部分,现在可以处理大文件了: 第二是学习了http://www.blogjava.net/killme2008/archive/2010/09/08/quicksort_optimized.html 中写的关于快速排序算法的优化改进,也移植到了我的程序里试了试. 分别使用两种方法处理同一份文件,大小是1M,不同的词有17000,这个大小的文件之前是一处理就崩溃的,算