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 }
  • 相关阅读:
    C# 全局变量
    [C#]续:利用键代码自动转换生成字母键或其它键信息
    [WPF](小结2)DataGrid嵌套DataGrid(也叫主从表)
    [C#]winform窗口托盘
    C# arrayList动态添加对象元素,并取出对象元素的方法
    [WPF](小结3)DataGridInTreeView树嵌表
    [WPF](小结4)TreeView的数据分层模板
    [WPF](小结1)ListBox嵌套ListBox
    [C#]利用键代码自动转换生成字母键或其它键信息
    [C#]使用API 获取设置系统热键和快捷键
  • 原文地址:https://www.cnblogs.com/csusheep/p/3237262.html
Copyright © 2011-2022 走看看