小培

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

1.插入排序的进化
  第一个版本的插入排序isort1:
  for i = [1,n)
         for(j=i; j>0 && x[j-1] > x[j]; j-- )
               swap(j-1,j);
  第一个思路,将swap函数内联化,或者替换为语句,节省函数切换时间
  isort2:
  for i = [1,n)
         for(j=i; j>0 && x[j-1] > x[j]; j-- )
        {
                t = x[j];
                x[j] = x[j-1];
                x[j-1] = t;
        }
  isort2是isort1运行时间的三分之一。
  继续优化,isort2中在每一次和前一位比较的时候,我们都需要给t赋值,把t值给其他变量,而且在这一个过程中t的值是一个,所以我们可以将它提取出来,在最后一次操作以后将值赋给最后的位置。
  isort3:
  for i = [1,n)
        t= x[i]; // x[i] 就是x[j]中第一个j的值
         for(j=i; j>0 && x[j-1] > x[j]; j-- )        
               x[j] = x[j-1];
        x[j]= t;

 

  isort3比isort2块15%。

  如果输入数组几乎是有序的,那么插入排序的速度会快很多,因为每个元素的移动距离很短。

2.快速排序
  快速排序对于大数据量的排序非常有效。
  第一个版本:
  void qsort1(l,u)
        ifl>= u           // l should little than u
               return;  
        m = l;            //use the first data to split, flagdata
        for i =[l+1,u]    //scan from the second data
               if( x[i] < x[l] ) // the data is little than thefirst data
                       swap(++m,i);  //m should little than i, swap the data
        swap(l,m); //m is the write data to set the flag data
        qsort1(1,m-1);
        qsort1(m+1,u);

  运用哨兵,进行代码优化
  void qsort2a(l,u)
        if l>=u           // l should little than u
               return;          
        t = x[l];         //use the first data to split, flag data
        m= u+1;
        for( i = u;i>=l;i--)
               if(x[i]>=t)    //even if x[i]== t, also swap
                       swap(--m,i);       
        qsort2a(1,m-1);
        qsort2a(m+1,u);
  对2a算法,利用哨兵进行二次优化:
  void qsort2aa(l,u)
        if l>=u           // l should little than u
               return;          
        t = x[l];         //use the first data to split, flag data
        m=i = u+1;
        do
           while x[--i] < t ;
           swap(--m,i);
        while i!=l

        qsort2aa(1,m-1);
        qsort2aa(m+1,u);
 
  哨兵位置变化的算法,哨兵变为x[u],
  void qsort2b(l,u)
        if l>=u           // l should little than u
               return;          
        t = x[u];         //use the first data to split, flag data
        m= l-1;
        fori = [l,u]
               if( x[i] <= t )
                       swap(++m,i);               
        qsort2b(1,m-1);
        qsort2b(m+1,u);
  对于qsort2b算法,利用哨兵进行的二次优化。
  void qsort2b(l,u)
        if l>=u           // l should little than u
               return;          
        t = x[u];         //use the first data to split, flag data
        m= i = l-1;
        do
           while x[++i] > t ;
           swap(++m,i);
        while i!=u;       
        qsort2b(1,m-1);
        qsort2b(m+1,u);
 

  对于拥有n个相同数据的数组,以上的算法,时间量级退化为为o(n*n).
  这个时候使用双向划分,数据相等的时候,停止。
  循环不变式为: t=x[l];l<=i<=j<=u;  l<a<b<u => x[a]<=x[b]
  下标i,j初始化为待划分数组的两端。主循环中有两个内循环,第一个内循环将i向右移过小元素,遇到大元素停止;第二个内循环将j向左移过大元素,遇到小元素停止。然后主循环测试这两个下标是否交叉并交换它们的值。
  但是当元素相同的时候,停止扫描,并交换i,j的值。
  实现代码:
  void qsort3(l,u)
        ifl>= u           // l should little than u
               return;          
        t = x[l]; //flag
        i = l; j= u+1;   //init the i,j
        loop
           do i++ while i<=u && x[i] < t
           do j++ while x[i] > t
            if i>j
               break
           swap(i,j);
        swap(l,j);
        qsort3(1,m-1);
        qsort3(m+1,u);
  针对qsort3的改善点:
   1.flag的值设置为第一个,当给的数据基本有序的时候,程序的性能会变差,所以可以用rand()函数定位,先将第一个数据和定位到的数据交换。提高性能。
   2.当l,u距离比较小的时候,快速排序的效率会降低,这个时候可以采用其他的排序方法进行排序,以提高整体的排序效率。
   3.将swap函数进行适当的展开。
  经过优化的函数为:
  void qsort4(l,u,coff)  //coff 停止扫描的u-l差距。一般设置为50.
        ifu-l<coff       // 停止扫描的阀值检测
               return;  
        swap(l,randint(l,u));       
        t = x[l]; //flag
        i = l; j= u+1;   //init the i,j
        loop
           do i++ while i<=u && x[i] < t
           do j++ while x[i] > t
            if i>j
               break
           temp=x[i]; x[i]=x[j]; x[j]=temp;   //展开swap
        swap(l,j);
        qsort4(1,m-1);
        qsort4(m+1,u);        

posted on 2010-11-05 20:58  小培  阅读(269)  评论(0)    收藏  举报