zoukankan      html  css  js  c++  java
  • 算法回顾(二):快速排序

    算法回顾(一)中,介绍了冒泡排序,它虽然很容易理解,但是效率却着实的低(O(N^2)), 现在让我们来回顾一下另外一种排序算法,它的效率可就高了许多,大概是O(N*logN),这就是 快速排序

    快速排序的中心思想就是:先从待排序的序列中,选择处于中间位置的关键码作为pivot,然后将剩下的元素进行一个筛选,将码值小于pivot的放到左边,码值大的放到右边。然后,分别对pivot左右两边的序列进行一次相同的筛选操作,依次类推,直到最后分的不能再分为止。这个时候整个序列就排序完成了。

    说起来简单,做起来难。真正把上面的思想写成代码还是需要下一番功夫的。一般这种情况,最佳实践就是先写出算法的伪代码,然后再用相应的程序语言完成。

    伪代码如下:

    quickSort(array, left, right)
        
        pivot = findpivot(array,left, right)//选择pivot中轴关键码
        
        partition(array,pivot) //对中轴两边进行筛选,小于pivot的放左边,大于pivot的放右边
    
        quickSort(array, left, pivot -1)//对pivot 左边的序列进行相同的操作
    
        quickSort(array, pivot +1, right)//对pivot 右边的序列进行相同的操作

    接下来根据这个伪代码使用c来实现:

    void quickSort( int a[], int i, int j ) //quickSort(array, left, right)
    {
        
        int pivot = findpivot(a, i, j); //pivot = findpivot(array,left, right)//选择pivot中轴关键码
    
        partition(a, i, j, pivot); // partition(array,pivot) //对中轴两边进行筛选,小于pivot的放左边,大于pivot的放右边
    
        quickSort(a, i, pivot -1); //quickSort(array, left, pivot -1)//对pivot 左边的序列进行相同的操作
    
        quickSort(a, pivot +1, j); //quickSort(array, pivot +1, right)//对pivot 右边的序列进行相同的操作
    }
    
    int  findpivot( int a[], int i, int j )
    {    
        return (i + j)/2;  
    }

    对于partition这个步骤有很多不同的实现,这里只介绍一种:

    1、设置两个标记,一个是最左,一个是最右

    2、从左开始遍历,遇到第一个大于pivot值时停止,

    3、然后从右开始遍历,直到遇到第一个小于pivot的关键码为止

    4、交换步骤2,3中的两个标记指向的关键码的值

    5、重复 2、3、4步 直到 定位右边的标记 小于 定位左边的标记为止

    实现代码如下:

    void partition(int a[], int l , int r, int pivot)
     {
         do{
          
             while (a[++l] < pivot) { //左标记从左往右不断遍历,直到碰到大于pivot的关键码
                  ;
             }
              
             while (a[--r] > pivot) {//右标记从右往左不断遍历,直到碰到小于pivot的关键码
                 ;
             }
             swap(a[l], a[r]); //交换这个两个关键码的值,使之符合左边小右边大的规律
         
         }while (l<r);// 循环便利结束条件:右边的标记比左边的标记小
     
     }

     运行,调试然后修改一些细节,我们就得到下面的完整的代码:

     1 int partition(int a[], int l , int r, int pivot)
     2 {
     3     do{
     4     
     5         while (a[++l] < pivot) {
     6             ;
     7         }
     8         
     9         while (a[--r] > pivot) {
    10             ;
    11         }
    12         swap(a[l], a[r]);
    13     
    14     }while (l<r);
    15     
    16     swap(a[l], a[r]); // 纠正上面遍历的最后一次 swap
    17     
    18     return l;
    19 
    20 }
    21 
    22 int findpivot(int a[], int i, int j)
    23 {
    24     return (i+j)/2;
    25 }
    26 
    27 void qsort(int a[], int i, int j)
    28 {
    29     if (j<=i) {
    30         return; //do not sort 0 or 1 item
    31     }
    32     int pivotindex = findpivot(a,i,j);
    33     
    34     swap(a[pivotindex], a[j]); // move the pivot at end
    35     
    36     int k = partition(a, i-1, j, a[j]);
    37     
    38     swap(a[k], a[j]);
    39     
    40     qsort(a, i, k-1);
    41     
    42     qsort(a, k+1, j);
    43 
    44 }
  • 相关阅读:
    hdu--2578--与女孩约会
    hdu--2588--欧拉函数||容斥原理
    hdu--2586--lca_tarjan<证明tarjan这个人很流弊>
    hdu--3743--归并排序<自顶向下&&自底向上>2种写法
    hdu--4911--归并排序||树状数组
    hdu--2639--01背包第K解<不同决策的不同解法>
    hdu--2642--二维BIT
    hdu--3833--4000ms才能过的O(N^2)算法
    hdu--3835--最简单的数学..
    hdu--3836--tarjan+缩点
  • 原文地址:https://www.cnblogs.com/csusheep/p/3237262.html
Copyright © 2011-2022 走看看