zoukankan      html  css  js  c++  java
  • 三向切分的快速排序

      快速排序在实际应用中会面对大量具有重复元素的数组。例如加入一个子数组全部为重复元素,则对于此数组排序就可以停止,但快排算法依然将其切分为更小的数组。这种情况下快排的性能尚可,但存在着巨大的改进潜力。(从O(nlgn)提升到O(n))

      一个简单的想法就是将数组分为三部分:小于当前切分元素的部分,等于当前切分元素的部分,大于当前切分元素的部分。

      E.W.Dijlstra(对,就是Dijkstra最短路径算法的发明者)曾经提出一个与之相关的荷兰国旗问题(一个数组中有分别代表红白蓝三个颜色的三个主键值,将三个主键值排序,就得到了荷兰国旗的颜色排列)。

      他提出的算法是: 对于每次切分:从数组的左边到右边遍历一次,维护三个指针,其中lt指针使得元素(arr[0]-arr[lt-1])的值均小于切分元素;gt指针使得元素(arr[gt+1]-arr[N-1])的值均大于切分元素;i指针使得元素(arr[lt]-arr[i-1])的值均等于切分元素,(arr[i]-arr[gt])的元素还没被扫描,切分算法执行到i>gt为止。每次切分之后,位于gt指针和lt指针之间的元素的位置都已经被排定,不需要再去处理了。之后将(lo,lt-1),(gt+1,hi)分别作为处理左子数组和右子数组的递归函数的参数传入,递归结束,整个算法也就结束。

    三向切分的示意图:

    C++代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 #define maxn 10000
     5 int a[maxn];
     6 
     7 void exchange( int i,int j )
     8 {
     9     int tmp=a[i];
    10     a[i]=a[j];
    11     a[j]=tmp;
    12 }
    13 
    14 
    15 void qsort3way ( int lo,int hi )
    16 {
    17     if( lo>=hi ) return;  //单个元素或者没有元素的情况
    18     int lt=lo;
    19     int i=lo+1;  //第一个元素是切分元素,所以指针i可以从lo+1开始
    20     int gt=hi;
    21     int v=a[lo];
    22     while( i<=gt )
    23     {
    24         if( a[i]<v )  //小于切分元素的放在lt左边,因此指针lt和指针i整体右移
    25             exchange( lt++,i++ );  
    26         else if ( a[i]>v )  //大于切分元素的放在gt右边,因此指针gt需要左移
    27             exchange( i,gt-- );
    28         else
    29             i++;
    30     }
    31     //lt-gt的元素已经排定,只需对it左边和gt右边的元素进行递归求解
    32     qsort3way( lo,lt-1 );    
    33     qsort3way( gt+1,hi );
    34 }
    35 
    36 
    37 int main()
    38 {
    39     int n;
    40     cin>>n;
    41     for( int i=0; i<n; i++  )
    42         cin>>a[i];
    43     qsort3way( 0,n-1 );
    44     for( int i=0; i<n; i++  )
    45         cout<<a[i];
    46     cout<<endl;
    47     return 0;
    48 }

    下面是《算法(第四版)》上对算法切分轨迹的一个示例说明:

      

    对于包含大量重复元素的数组,这个算法将排序时间从线性对数级降到了线性级别。

  • 相关阅读:
    UCMap移动GIS & 时空地图GIS
    LCA模板
    如何在Mac OSX上安装xgboost
    java 文件操作
    Java Date与SimpleDateFormat
    hdu 5713(状态压缩DP)
    JAVA 程序设置运行内存
    TCP/IP 小知识
    hadoop 入门实例【转】
    【JDK1.8】JDK1.8集合源码阅读——TreeMap(二)
  • 原文地址:https://www.cnblogs.com/kiwibird/p/5026489.html
Copyright © 2011-2022 走看看