随机方法避免快排最坏情况,快排中引入插入排序提速分析

1快速排序算法基本思想:

QuickSort(A,p,r)

         if p<r

                   then q<- PARTITION(A,p,r) 1//选择位置q,将数组分为两部分

                   QuickSort(A,p,q-1)     

                   QuickSort(A,q+1,r)

PARTITION(A,p,r)

         x<- A[r]

         i<- p-1     //定义i为活动指针,向右移动并使A[p…i]<=x

         for j<- p to r-1  //定义j为遍历数组A

                   do if A[j]<= x

                            then i< i+1 //右移并交换,使满足<=x的元素增加一个

                                     exchange A[i]<->A[j]

         exchange A[i+1]<->A[r] 

//将A[r]放入i+1位置,使p…i项均小于i+1项,后A[i+2…r]项均大于A[i+1]

         return i+1

2改进优化方法:

一、通过采用随机方法,避免最坏情况发生:

在原方法中,选择比较元素为数组最后一个元素。通过随机函数,生成位于p~r之间的随机数为比较项位置(A[random(p,r)]),与原先比较元素(A[r])位置交换,再调用PARTITION方法,伪代码如下:

//该方法能对数组中已经存在部分有序队列的情况进行优化,避免最坏情况发生

Random_PARTITION(A,p,r)

         i<- Rand(p,r)

         exchange A[i]<->A[r]

return PARTITION(A,p,r)

         将Random_PARTITION方法在1处调用即可。

二、当问题规模小于某一k值时,采用插入排序,提高算法效率

修改当r-p<k值时,调用InsertSort方法

修改后方法伪代码为:

QuickSort(A,p,r)

         if r-p<k

                   InsertSort(A,p,r)

         else if p<r

                   then q<- Random_PARTITION (A,p,r)

                   QuickSort(A,p,q-1)     

                   QuickSort(A,q+1,r)

        

 

k值的讨论取值:

算法复杂度为O(nk+nlog(n/k)),对于每一项的系数有插入排序复杂度为0.5*k*(k-1)*(n/k)=1/2*n*k,可以取nk项系数为c1=1/2。对于采用原快排序的部分,有期望为nlog(n/k),通过递归树证明略,取c2=1,则有下式:

令F(k)= c1*nk+c2*nlog(n/k)=0.5*nk+nlog(n/k)

对F(k)求导,一阶导数=0,二阶导数>0,则有:

k=2/ln2

对k取值约等于3时有最小值,即问题规模<=3时采用插入排序效率更高。

 

对K值的讨论:

k=3时 0.20s

k=6时0.18s

k=7时0.18s

k=50时0.19s

k=100时0.20s

分析,因为实验环境是core i5 处理器能力较强,对于1000000(1百万)数据时间耗时较短差别较小。在k取7~30左右可有较好范围的实验结果。

 

实验结果:

实验环境:Ubuntu_x64语言:C++ 数据规模:

实验数据1000000 处理器i5 4核

采用插入排序优化后结果:耗时0.194s  k取值为4

直接使用快排结果:耗时0.203S

采用随机方法于原算法比较:

对已经排好序的数组进行排序,对最坏情况进行分析:

问题规模:10000 不采用random 0.138S

采用random方法0.002s

实验结果明显,通过采用随机元素位置,可以避免坏情况带来的特殊值,使算法更接近于时间期望。

原文链接:http://www.cnblogs.com/sunshinewill/archive/2013/03/05/2943642.html

View Code
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
void Insertsort(int list[],int a,int b){
    int next,j;
    if(a>b)return;
    for(int x=a;x<=b;x++){
    next=list[x];
    for(j=x-1;j>=a&&next<list[j];j--)
        list[j+1]=list[j];
    list[j+1]=next;
    }

}

void quicksort(int list[],int left,int right)
{
 int pivot,i,j;
 int temp,pos;
 //k取值为10
 if(right-left<10){Insertsort(list,left,right);}else
 if(left<right)
 {//注明:在实现过程中,采用i,j从两边向中间遍历的方法,可进一步提高算法的速度
  i=left;
  j=right+1;
  pos=rand()%(right-left)+left;//采用随机方法
 pivot=list[pos];
  temp=list[left];
  list[left]=list[pos];
  list[pos]=temp;
//pos =left;
  do
  {
   do i++;
   while(list[i]<pivot);
 
   
   do j--;
   while(list[j]>pivot);
   if(i<j)
   {temp=list[i];
   list[i]=list[j];
   list[j]=temp;}
  }while(i<j);

  temp=list[left];
  list[left]=list[j];
  list[j]=temp;
  quicksort(list,left,j-1);
  quicksort(list,j+1,right);
 }
 else return;
}

int main()
{
 int i;
 int n=1000000;
 int list[1000000];

 srand((unsigned)time(NULL));
 for(i=0;i<n;i++)
 list[i]=rand();

 quicksort(list,0,n-1);
// for(i=0;i<n;i+=20)
// cout<<" "<<list[i];

 return 0;  
}

 

posted @ 2013-03-05 00:34  SONGHY  阅读(2647)  评论(1编辑  收藏  举报