排序算法 - 快速排序(Quick Sort)

算法思想

 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

(1) 分治法的基本思想
     分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

(2)快速排序的基本思想
     设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
分解: 
     在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
  注意:
     划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
     R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
                  其中low≤pivotpos≤high。
求解: 
     通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

组合: 
     因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

代码实现(Java)

  1 public class QuickSort {
  2
  3     private Double[] source;
  4     private int TYPE;
  5     private Object result;
  6
  7     public QuickSort(Double[] source) {        //Double类型构造
  8         this.source = source;
  9         result = source;
 10         TYPE = 0;
 11     }
 12     public QuickSort(double[] source) {        //double类型构造
 13         this.source = new Double[source.length];
 14         for (int i = 0; i < source.length; i++) {
 15             this.source[i] = source[i];
 16         }
 17         result = source;
 18         TYPE = 1;
 19     }
 20     public QuickSort(int[] source) {        //int类型构造
 21         this.source = new Double[source.length];
 22         for (int i = 0; i < source.length; i++) {
 23             this.source[i] = (double) source[i];
 24         }
 25         result = source;
 26         TYPE = 2;
 27     }
 28
 29     public void sort() {
 30         if (source != null) {
 31             sort(0, source.length - 1);
 32             switch (TYPE) {
 33             case 0:
 34                 break;
 35             case 1:
 36                 {
 37                     for (int i = 0; i < source.length; i++) {
 38                         ((double[]) result)[i] = source[i].doubleValue();
 39                     }
 40                 }
 41                 break;
 42             case 2:
 43                 {
 44                     for (int i = 0; i < source.length; i++) {
 45                         ((int[]) result)[i] = source[i].intValue();
 46                     }
 47                 }
 48                 break;
 49             }
 50         }
 51     }
 52
 53     /**
 54      * @param left : 左指针
 55      * @param right : 右指针
 56      * @category 递归排序
 57      * */
 58     private void sort(int left, int right) {
 59         if (right <= left) return;
 60         int l = left;                                //左边界
 61         int r = right;                                //右边界
 62         double base = source[left];                    //参照数
 63         boolean done = true;                        //上一轮是否进行了交换,这里定义,每进行一次定方向的比较查找 就算是一轮
 64         while (left < right) {
 65             //倒序
 66             if (!done) break;
 67             done = false;
 68             for (int i = right; i > left; i--) {
 69                 if (source[i] < base) {                //这里的base肯定指向 source[left],不然不会进行到【倒序】
 70                     double t = source[left];
 71                     source[left] = source[i];
 72                     source[i] = t;
 73                     right = i;
 74                     done = true;
 75                     break;
 76                 }
 77             }
 78             //正序
 79             if (!done) break;
 80             done = false;
 81             for (int i = left; i < right; i++) {
 82                 if (source[i] >= base) {            //这里的base肯定指向 source[right],不然不会进行到【正序】
 83                     double t = source[right];
 84                     source[right] = source[i];
 85                     source[i] = t;
 86                     left = i;
 87                     done = true;
 88                     break;
 89                 }
 90             }
 91         }
 92         //递归
 93         if (source[left] == base) {
 94             sort(l, left - 1);
 95             sort(left + 1, r);
 96         } else {
 97             sort(l, right - 1);
 98             sort(right + 1, r);
 99         }
100     }
101 }

测试代码

 1 public class Test {
 2
 3     /**
 4      * @author Wfei
 5      */
 6     public static void main(String[] args) {
 7         int[] source_int = new int[20];
 8         Double[] sourceDou = new Double[20];
 9         double[] source_dou = new double[20];
10         for (int i = 0; i < source_int.length; i++) {
11             int t = (int) (Math.random() * 20);
12             source_int[i] = t;
13             sourceDou[i] = (double) t;
14             source_dou[i] = (double) t;
15         }
16         long beginTime;
17         long endTime;
18
19         printData(source_int);
20         QuickSort quickSort = new QuickSort(source_int);
21
22         beginTime = new Date().getTime();
23         quickSort.sort();
24         endTime = new Date().getTime();
25
26         printData(source_int);
27         System.out.println("耗时  : " + (endTime - beginTime) + " 毫秒");
28     }
29
30     private static void printData(int[] source) {
31         for (int i = 0; i < source.length; i++) {
32             if (i % 10000 == 0) {
33                 System.out.println("");
34             }
35             System.out.print(source[i] + " , ");
36         }
37         System.out.println("");
38     }
39 }

声明:以上实现,纯属个人初次学习《快速排序》思想所得,暂未参见其他前辈高明的实现算法思想,持续学习更新中!

引用:快速排序理论思想,请参见:http://www.cnblogs.com/foreverking/articles/2234225.html

时间: 2024-11-06 01:34:55

排序算法 - 快速排序(Quick Sort)的相关文章

经典排序算法 - 快速排序Quick sort

经典排序算法 - 快速排序Quick sort 原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列 举个例子 如无序数组[6 2 4 1 5 9] a),先把第一项[6]取出来, 用[6]依次与其余项进行比较, 如果比[6]小就放[6]前边,2 4 1 5都比[6]小,所以全部放到[6]前边 如果比[6]大就放[6]后边,9比[6]大,放到[6

算法---快速排序(quick sort)

在前面介绍的排序算法中,最快的排序算法为归并排序,但是归并排序有一个缺陷就是排序过程中需要O(N)的额外空间.本文介绍的快速排序算法时一种原地排序算法,所需的额外空间复杂度为O(1). 算法介绍:快速排序其实一种根据需找某个元素的具体位置进行排序的方法.比如所存在如下数组 选择第一个元素5,找到5最终的位置,即5的左边的数都小于或者等于5,右边的数都大于或者等于5. 从"6"开始,可知6大于5,此处停住,从"2"开始2小于5,因此交换6与2的位置,然后接着往下走,将

排序:快速排序Quick Sort

原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列 举个例子 如无序数组[6 2 4 1 5 9] a),先把第一项[6]取出来, 用[6]依次与其余项进行比较, 如果比[6]小就放[6]前边,2 4 1 5都比[6]小,所以全部放到[6]前边 如果比[6]大就放[6]后边,9比[6]大,放到[6]后边,//6出列后大喝一声,比我小的站前边,比

排序算法----快速排序java

快速排序是对冒泡排序的一种改进,平均时间复杂度是O(nlogn) import java.util.Arrays; import java.util.Scanner; public class test02{ public static void main(String[] args) { int n = 1; while (n != 0){ Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); int s[] = ne

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

经典排序算法 – 插入排序Insertion sort

经典排序算法 – 插入排序Insertion sort  插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行.   图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入. 以下代码仅供参考,欢迎指正 /// <summary> /// 插入排序 /// </summary> /// <param na

经典排序算法 - 堆排序Heap sort

经典排序算法 - 堆排序Heap sort 堆排序有点小复杂,分成三块 第一块,什么是堆,什么是最大堆 第二块,怎么将堆调整为最大堆,这部分是重点 第三块,堆排序介绍 第一块,什么是堆,什么是最大堆 什么是堆 这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构. 堆可以视为一棵完全的二叉树,完全二叉树的一个"优秀"的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素. 数组与堆之间的关系 二叉堆一般分为两种:最大堆和最小堆. 什么

经典排序算法 - 基数排序Radix sort

经典排序算法 - 基数排序Radix sort 原理类似桶排序,这里总是需要10个桶,多次使用 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数 例如 待排序数组[62,14,59,88,16]简单点五个数字 分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样 |  0  |  0  | 62 |  0  | 14 |  0  | 16 |  0  |  88 | 59 | |  0  |  1  |  2  |  3  |  4 |