四种快排与两种归并和堆和插入排序 大数据量运行时间比较

#include"iostream"
#include"iomanip"
#include"stdlib.h"
#include"time.h"
#include"string"
/*由于我电脑内存有限所以数据量最大能运行在20w*/




//三路快排适用于有大量重复值的数据 
//四种快排与两种归并和堆和插入排序 大数据量运行时间比较 
//快排一:quickSort 有可能退化为O(n^2)
//快排二:quickSort2对快排一的问题进行了优化 
//快排三:quickSort3采用三路快排,用的是快排一的编码方式 
//快排四:quickSort4采用三路快排,用的是快排二的编码方式 
//归并一:merge_sort采用递归自下向上排序 
//归并二:merge_sortBU采用非递归自上向下排序,适用于链表排序 
//堆排序:heapSort
//插入:insert_sort
//测试得 “快排四”运行的相对时间最少 
using namespace std;
int *Factory(int n,int x,int y)//产生x和y之间的n个数 
{
srand(time(NULL));
int *arr=new int[n];
for(int i=0;i<n;i++){
arr[i]=rand()%(y-x)+x;
}
return arr;
}
void clock_calculate(string name,void (*sort)(int *a,int n),int *a,int n)//测试时间函数 
{
time_t start=clock();
sort(a,n);
time_t end=clock();
cout<<name<<":\t\t"<<(end-start)*1.0/1000<<"s"<<endl; 
}
int *copyArr(int *a,int n)//拷贝数组函数 
{
int *a1=new int[n];
for(int i=0;i<n;i++){
a1[i]=a[i];
}
return a1;
}
/****************************************************************************/
void __quickSort4(int *a,int l,int r){
if(r>l){
swap(a[l],a[rand()%(r-l+1)+l]);
int t=a[l];
int i=l+1,j=r,lt=l+1;//lt始终指向最前面的等于t的元素,i是第一个没有处理的数据 
while(i<=j)//j指向最后一个没处理的
{
while(i<=j&&a[i]<=t){
if(a[i]==t){//遇见相等的则i向前走,lt指向第一个等于t的元素 
i++;
}else if(i==lt){//当i==lt说明没有遇见跟t相等的元素 
i++,lt++;
}else{//i!=lt说明有重复的t,将i跟lt进行交换 
swap(a[i],a[lt]);
i++,lt++;
}
}
while(i<=j&&a[j]>t){
j--;
}
if(i>j)
break;
swap(a[i],a[j]);
j--;

swap(a[l],a[lt-1]);
__quickSort4(a,l,lt-2);
__quickSort4(a,j+1,r);
}
}
void quickSort4(int a[],int len){
srand(time(NULL));
__quickSort4(a,0,len-1);
}


/***********************************************************************/
void __quickSort3(int *a,int l,int r){
if(r>l){
swap(a[l],a[rand()%(r-l+1)+l]);
int t=a[l];
int i=l+1,j=r,lt=l+1;
while(i<=j)//j指向最后一个没处理的
{
if(a[i]<t) { 
swap(a[i],a[lt]);
i++,lt++;
}else if(a[i]>t){
swap(a[i],a[j]);
j--;
}else{
i++;
}

swap(a[l],a[lt-1]);
__quickSort3(a,l,lt-2);
__quickSort3(a,j+1,r);
}
}
void quickSort3(int a[],int len){
srand(time(NULL));
__quickSort3(a,0,len-1);
}
/****************************************************************************/
int partition(int a[],int l,int r){

swap(a[l],a[rand()%(r-l+1)+l]);//随机产生中间的标志 
int t=a[l];//当数组近乎有序的时候退化为O(n^2) 所以添加以上代码 
int i,j;
for(j=l,i=l+1;i<=r;i++){
if(a[i]<t){
swap(a[j+1],a[i]);
j++;
}//j+1一直指向不小于t的数 j一直指向不大于t的数 
}
swap(a[l],a[j]);
return j;
}
void __quickSort(int *a,int l,int r){
if(r>l){
int p=partition(a,l,r);
__quickSort(a,l,p-1);
__quickSort(a,p+1,r);
}
}
void quickSort(int a[],int len){
srand(time(NULL));
__quickSort(a,0,len-1);
}
/******************************************************************************/
int partition2(int a[],int l,int r){
swap(a[l],a[rand()%(r-l+1)+l]);
int t=a[l];
int i=l+1,j=r;
while(i<=j){//用i==j的条件去确定j的位置 
while(i<=j&&t>=a[i]) i++;
while(i<=j&&t<=a[j]) j--; 
//执行前面的代码 不可能让i==j 因为不可能有一个数既满足i又满足j 
if(i>j)//一种情况利用i==j的情况 然后让i ,j递变 让j指向中间位置 
break;
swap(a[i],a[j]);
i++;
j--;//如果用i<j条件 1.当执行完这步后i,j指向的两个都小于t,再进循环就只判断了i, 不会进j的循环,那j和i指向的就是中间位置
// 2.当执行完最后一步后两个都满足j,那么就不会进入i的循环,j等于i,i的前一个就是中间位置 

swap(a[l],a[j]);
return j;
}
void __quickSort2(int *a,int l,int r){
if(r>l){
int p=partition2(a,l,r);
__quickSort2(a,l,p-1);
__quickSort2(a,p+1,r);
}
}
void quickSort2(int a[],int len){
srand(time(NULL));
__quickSort2(a,0,len-1);
}
/*******************************************************************************/
void merge(int *a,int l,int m,int r)
{
int tmp[r-l+1];
int i,j,k;
for(i=l;i<=r;i++){
tmp[i-l]=a[i];
}
for(i=l,j=m+1,k=l;k<=r;k++){
if(i>m){
a[k]=tmp[j-l];
j++;
}else if(j>r){
a[k]=tmp[i-l];
i++;
}else if(tmp[i-l]>tmp[j-l]){
a[k]=tmp[j-l];
j++;
}else{
a[k]=tmp[i-l];
i++;
}
}
}
/*自底向上归并*/
void _merge_sort(int *a,int left,int right){
int mid=(left+right)/2;
if(right!=left){
_merge_sort(a,left,mid);
_merge_sort(a,mid+1,right);
if(a[mid]>a[mid+1]);{
merge(a,left,mid,right);
}
}
}
void merge_sort(int *a,int len){
_merge_sort(a,0,len-1);
}
/***********************************************************************************/
void insert_sort(int a[],int n){
int result=1;
for(int i=0;i<n&&result;i++){
result=0;
for(int j=0;j<n-i+1;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
result=1;
}
}
}
}
/*******************************************************************************/
/*自顶向下归并*/
int min(int a,int b){
return a>b?b:a;
}
void merge_sortBU(int a[],int len){
for(int sz=1;sz<=len;sz+=sz){//每次归并的长度 
for(int i=0;i+sz<len;i+=sz+sz){//i+sz<len保证归并有右半部分(至少有两个部分) 
//对a[i...i+zs-1]和a[i+sz...i+sz+sz-1]进行归并 
merge(a,i,i+sz-1,min(i+sz+sz-1,len-1));//没有使用数组索引 更方便对链表这种数据结构进行排序 
}
}
}
/**********************************************************************************/
//堆排序 
void __shiftDown(int a[],int n,int k)
{
while((k*2+1)<n)
{
int j=k*2+1;
if((j+1)<n&&a[j+1]>a[j])
{
j++;
}
if(a[k]>=a[j])
break;
swap(a[k],a[j]);
k=j;
}

}
void heapSort(int a[],int n)
{
for(int i=(n-1)/2;i>=0;i--)
{
//将数组a的n个元素的第i个节点进行位置调整形成最大堆 
//数组索引从0开始的堆 共有 (n-1)/2个非叶子节点 
__shiftDown(a,n,i);
}
//创建好最大堆后进行堆排序
for(int i=n-1;i>0;i--)
{
swap(a[0],a[i]);
//将共有i个节点的堆a,第0个节点进行调整 
__shiftDown(a,i,0);
}
}


int main()
{
int N=200000;//数据量 
int min_data=0,max_data=1000;
int *a=Factory(N,min_data,max_data);//产生N个[min_data,max_data)之间的数 
int *a2=copyArr(a,N);//拷贝产生的第一个随机数,以供其他排序算法使用 
int *a3=copyArr(a,N);
int *a4=copyArr(a,N);
int *a5=copyArr(a,N);
int *a6=copyArr(a,N);
int *a7=copyArr(a,N);
int *a8=copyArr(a,N);
printf("数据量:%d\n",N);
printf("数据取值范围:[%d,%d)\n",min_data,max_data);
printf("\n----------------------------------------------------\n\n");
clock_calculate("quickSort",quickSort,a,N);//计算排序的运行时间 
clock_calculate("quickSort2",quickSort2,a2,N);
clock_calculate("quickSort3",quickSort3,a3,N);
clock_calculate("quickSort4",quickSort4,a4,N);
clock_calculate("merge_sort",merge_sort,a5,N);
clock_calculate("merge_sortBU",merge_sortBU,a6,N);
clock_calculate("heapSort",heapSort,a7,N);
clock_calculate("insert_sort",insert_sort,a8,N);
delete [] a;
delete [] a2;
delete [] a3;
delete [] a4;
delete [] a5;
delete [] a6;
delete [] a7;
delete [] a8;

}


猜你喜欢

转载自blog.csdn.net/qq_40279887/article/details/80072996
今日推荐