最近在复习算法,下面是我自己整理的程序
普通情况下的最快的排序算法——快速排序
下面直接贴代码~
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>
using namespace std;
/**
因为测试排序的数据有1,000,000条,且使用数组0号位作为两数交换时的temp空间,再加上文件末尾空行,所以数组空间为1000002
**/
static const int ArraySize = 1000002;
/**
交换两个数,使用数组0号位
**/
template <typename Item>
void exch(Item a[],const int x,const int y)
{
a[0]=a[x];
a[x]=a[y];
a[y]=a[0];
}
/**
把小的值放在前面
**/
template <typename Item>
void compexch(Item a[],const int x,const int y)
{
if ( a[x] > a[y] ) exch( a,x,y );
}
/**
算法I-IV(C++实现)中的插入排序,因为在后面的优化的排序算法中需要使用到,因此也贴出来
**/
template <typename Item>
void insertion(Item a[],const int l,const int r)
{
for (int i = r; i > l; --i)//把最小的值放在最左边
compexch(a,i-1,i);
for (int i = l+2; i <= r; ++i)//从第三个开始遍历数组,并插入到前面已排好序的序列中(保持排序)
{
int j=i;
Item v=a[i];
while(v<a[j-1])//比待插入的数大的数往后移动
{
a[j] = a[j-1];
--j;
}
a[j] = v;
}
}
/**
数据结构 严蔚敏版的划分函数:
**/
template <typename Item>
int partition_v1(Item a[],const int l,const int r)
{
Item temp = a[l];
int i = l,j=r;
while( i < j )
{
while(i < j && a[j] >= temp) --j;
if(a[j]<temp){
a[i] = a[j];
++i;
}
while(i < j && a[i] <= temp) ++i;
if(a[i]>temp){
a[j] = a[i];
--j;
}
}
a[i] = temp;
return i;
}
/**
数据结构 严蔚敏版的快速排序(1,000,000条数据使用0.25s)
**/
template <typename Item>
void quicksort1(Item a[],const int l,const int r)
{
if(l<r){
int i = partition_v1(a,l,r);
quicksort1(a, l, i-1);
quicksort1(a, i+1, r);
}
}
template <typename Item>
void quicksort1_1(Item a[],const int l,const int r)
{
if(r-l>M){
int i = partition_v1(a,l,r);
quicksort1(a, l, i-1);
quicksort1(a, i+1, r);
}
else
{
insertion(a,l,r);
return ;
}
}
template <typename Item>
void quicksort1_2(Item a[],const int l,const int r)
{
if(r-l>M){
exch(a, (r+l)/2, r-1);
compexch(a, l, r);
compexch(a, l, r-1);
compexch(a, r-1, r);
int i = partition_v1(a,l+1,r-1);
quicksort1(a, l, i-1);
quicksort1(a, i+1, r);
}
else
{
insertion(a,l,r);
return ;
}
}
/**
算法I-IV(C++实现) 的划分函数:
**/
template <typename Item>
int partition_v2(Item a[],const int l,const int r)
{
int i = l-1,j=r;
Item v= a[r];
while (1)
{
while (a[++i] < v) ;
while (v < a[--j]) if (j == i) break;
if (i>=j) break;
exch(a,i,j);
}
exch(a,i,r);
return i;
}
/**
算法I-IV(C++实现) 的快速排序:原始版本(1,000,000条数据平均使用0.374s)
**/
template <typename Item>
void quicksort2(Item a[],const int l,const int r)
{
if (r <= l) return;
int i = partition_v2(a,l,r) ;
quicksort2(a,l,i-1);
quicksort2(a,i+1,r);
}
/**
算法I-IV(C++实现) 的快速排序:使用插入排序改进版(1,000,000条数据平均使用0.39s)
**/
static const int M=10;
template <typename Item>
void quicksort2_1(Item a[],const int l,const int r)
{
if( r-l <= M){
insertion(a,l,r);
return ;
}
int i = partition_v2(a,l,r) ;
quicksort2_1(a,l,i-1);
quicksort2_1(a,i+1,r);
}
/**
算法I-IV(C++实现) 的快速排序:三个数的中值+先快速排序再插入排序改进版(1,000,000条数据平均使用0.31s)
**/
template <typename Item>
void quicksort2_2(Item a[],const int l,const int r)
{
if( r-l <= M) return ;
//取最左、最右、以及中间三个值中的中值作为划分元素
exch(a, (l+r)/2, r-1);
compexch(a, l, r-1);
compexch(a, l, r);
compexch(a, r-1, r);
int i = partition_v2(a,l+1,r-1) ;
quicksort2_2(a,l,i-1);
quicksort2_2(a,i+1,r);
}
template <typename Item>
void hybirdsort(Item a[],const int l,const int r)
{
quicksort2_2(a,l,r);
insertion(a,l,r);
}
/**
算法I-IV(C++实现) 的快速排序:三路划分(1,000,000条数据平均使用0.36s)
**/
template <typename Item>
int operator==(const Item &A,const Item &B)
{
return !less(A,B) && !less(B,A);
}
template <typename Item>
void quicksort2_3(Item a[],const int l,const int r)
{
int k;Item v=a[r];
if (r<=l) return;
int i = l-1,j=r,p=l-1,q=r;
while (1)
{
while (a[++i]<v) ;
while (v<a[--j]) if (j==l) break;
if (i>=j) break;
exch(a,i,j);
if(a[i] == v ){p++;exch(a,p,i);}
if(a[j] == v ){p++;exch(a,q,j);}
}
exch(a,i,r);j=i-1;i=i+1;
for (k=l ; k<=p; ++k,--j) exch(a,k,l);
for (k=r-1; k>=q; --k,++i) exch(a,k,i);
quicksort2_3(a,l,j);
quicksort2_3(a,i,r);
}
/**
算法导论 的划分函数
**/
template<typename Item>
int partition_v3(Item a[],const int l,const int r)
{
Item x = a[r];
int i = l-1;
for (int j = l; j<r ;++j)
{
if (a[j]<x)
{
++i;
exch(a,i,j);
}
}
exch(a,i+1,r);
return i+1;
}
/**
算法导论 的划分函数随机化版本:随机选区划分元素
**/
template<typename Item>
int partition_v3_rand(Item a[],const int l,const int r)
{
srand((unsigned)time(NULL));
int i = 1 + (rand()*100)%(r-l);
exch(a,r,l+i);
return partition_v3(a,l,r);
}
/**
算法导论 的快速排序(1,000,000条数据平均使用0.65s)
**/
template<typename Item>
void quicksort3(Item a[],const int l,const int r)
{
if (l<r)
{
int i = partition_v3(a,l,r);
quicksort3(a,l,i-1);
quicksort3(a,i+1,r);
}
}
/**
算法导论 的快速排序 :随机化版本(1,000,000条数据平均使用0.75s)
**/
template<typename Item>
void quicksort3_rand(Item a[],const int l,const int r)
{
if (l<r)
{
int i = partition_v3_rand(a,l,r);
quicksort3_rand(a,l,i-1);
quicksort3_rand(a,i+1,r);
}
}
/**
读文件 inFile , 会把data数组中的内容全部清空,并重新分配空间
**/
template <typename Item>
bool readData(const char* inFileName , Item *data)
{
ifstream inFile(inFileName);
if (inFile.fail())
{
cout<<"文件操作失败!"<<endl;
inFile.close();
return false;
}
for (int i=1;i!=ArraySize-1;++i)
{
inFile>>data[i];
}
inFile.close();
if (data == NULL)
{
return false;
}
return true;
}
/**
写文件 outFile
**/
template <typename Item>
bool writeData(const char* outFileName, Item data[])
{
ofstream outFile(outFileName);//打开并清空文件
if( outFile.fail())
{
cout<<"文件操作失败!"<<endl;
outFile.close();
return false;
}
for (int i=1; i!=ArraySize; ++i)
{
outFile<<data[i]<<endl;
}
outFile.flush();
outFile.close();
return true;
}
/**
数组拷贝
**/
template <typename Item>
void arrayClone(Item sourceArray[],Item targetArray[])
{
for (int i=0; i != ArraySize; ++i)
{
targetArray[i] = sourceArray[i];
}
}
/**
调用排序(只调用writeData,因此在使用此函数前必须先把文件数据读入数组data中)
**/
template <typename Item>
void mySort(Item data[],void (*pFunc)(Item a[],const int l,const int r))
{
clock_t start_time,end_time;
double totaltime;
start_time = clock();//计时开始
pFunc(data,1,ArraySize-2);
end_time = clock();//计时结束
//totaltime=(double)(end_time-start_time)/CLOCKS_PER_SEC;
//cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
totaltime=(double)(end_time-start_time);
cout<<"\n此程序的运行时间为"<<totaltime<<"ms!"<<endl;
}
/**
调用排序算法进行排序
**/
template <typename Item>
bool mySort(const char* inFileName,
const char* outFileName,
void (*pFunc)(Item a[],const int l,const int r))
{
ifstream inFile(inFileName);//打开输入文件
ofstream outFile(outFileName);//打开并清空文件
if(inFile.fail() || outFile.fail())
{
cout<<"文件读取失败!"<<endl;
outFile.close();
inFile.close();
return false;
}
Item *a = new Item[ArraySize];
for (int i=1;i!=ArraySize-1;++i)
{
inFile>>a[i];
}
clock_t start_time,end_time;
double totaltime;
start_time = clock();//计时开始
pFunc(a,1,ArraySize-2);
end_time = clock();//计时结束
totaltime=(double)(end_time-start_time)/CLOCKS_PER_SEC;
cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
for (int i=1;i!=ArraySize-1;++i)
{
outFile<<a[i]<<endl;
}
delete []a;
inFile.close();
outFile.flush();
outFile.close();
return true;
}
下面是测试结果: