/*10、多种基本内排序方法的实现
问题描述:设计一个合成的排序程序。可供排序的方法是:
插入排序、快速排序、归并排序、堆排序。
要求程序具有
(1)显示排序结果.
(2)提供最好和最坏情况下对比计时的功能。
(3)提供在不同数组元素的个数情况
(当N分别等于100,1000,5000,20000时)
下各种排序算法的计算时间的统计功能。*/
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define T 1000;
bool cmp(int a,int b) //重写sort()的比较函数
{ //使其实现从大到小的排序
return a>b;
}
void swap(int &a,int &b)
{
int t;
t=a;a=b;b=t;
}
//插入排序
void insert(int a[],int l,int i)
{
/*元素a[i]插入数组a[l:i]*/
int m=a[i]; //m表示要插入的元素
int k=i-1;
while(a[k]>m&&k>=l)
{
a[k+1]=a[k];
k--;
}
a[k+1]=m;
}
void insertionsort(int a[],int l,int r)
{
/*l,r分别为数组的上下界*/
for(int i=l+1;i<=r;i++)
insert(a,l,i);
}
//快速排序
int partition(int a[],int l,int r)
{ /*返回划分结果*/
int i=l,j=r; //初始化
/* 将大于基准元素的记录放到右边
将小于基准元素的记录放到左边*/
while(i<j)
{
while(i<j&&a[i]<=a[j]) j--; //右侧扫描
if(i<j)
{
swap(a[i],a[j]) ; //将较小的记录交换到前面
i++;
}
while(i<j&&a[i]<=a[j]) i++; //左侧扫描
if(i<j)
{
swap(a[i],a[j]); //将较大的记录交换到后面
i++;
}
}
return i;
}
void quicksort(int a[],int l,int r)
{
if(l>r) return ;
int i=partition(a,l,r); //得到划分点
quicksort(a,l,i-1); //对左半部分进行快排
quicksort(a,i+1,r); //对右半部分进行快排
}
//归并排序
void copy(int a[],int b[],int l,int r)
{
for(int i=l;i<=r;i++)
a[i]=b[i];
}
void merge(int b[],int a[],int l,int mid,int r)
{ /*合并a[l:m]和a[m+1:r]到b[l:r]*/
int k=l,i=l,j=mid+1;
while(i<=mid&&j<=r) //合并a[l--mid]与a[mid+1,r]
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
while(i<=mid) b[k++]=a[i++]; //收尾处理
while(j<=r) b[k++]=a[j++];
}
void mergesort(int b[],int a[],int l,int r)
{
int mid=(r+l)/2; //划分
if(r<=l) return ; //递归结束条件
mergesort(b,a,l,mid); //对左边部分进行归并排序
mergesort(b,a,mid+1,r); //对右半部分进行归并排序
merge(b,a,l,mid,r); //将左右有序的数组a合并到数组b
copy(a,b,l,r); //将排好序的数组b复制回a
}
//堆排序
void heapRebuild(int arr[],int root,int size)
{
int child=2*root+1;
if(child<=size-1)
{
int rightChild=child+1;
if(rightChild<=size-1)
if(arr[child]<arr[rightChild])
child=rightChild;
if(arr[root]<arr[child])
{
int temp=arr[child];
arr[child]=arr[root];
arr[root]=temp;
heapRebuild(arr,child,size);
}
}
}
void heapsort(int arr[],int size)
{
int i;
for( i=size-1;i>=0;i--)
{
heapRebuild(arr,i,size);
}
int last=size-1;
for(i=1;i<=size;i++,last--)
{
int temp=arr[0];
arr[0]=arr[last];
arr[last]=temp;
heapRebuild(arr,0,last);
}
}
int a[1000000+10],b[1000000+10],c[1000000+10];
int main()
{
int i,k,m1,m,flag1,flag2,N,t;
clock_t start,finish;
double totaltime;
char ch;
while(1)
{
flag1=0;
cout<<endl;
cout<<"**************************主菜单***************************"<<endl<<endl;
//cout<<"*******************请输入编号选择所需操作******************"<<endl;
cout<<"***********1:选用不同的排序算法排序并查看结果**************"<<endl;
cout<<"***********2:查看不同排序算法最好和最坏情况下的时间开销****"<<endl;
cout<<"***********3:查看不同元素个数下各种不同算法的时间开销******"<<endl;
cout<<"***********4:退出系统**************************************"<<endl;
cout<<endl;
cout<<"请输入编号选择操作: ";
while(cin>>k)
{
if(k<=0||k>4)
cout<<"输入有误!请重新输入: ";
else
break;
}
cout<<endl;
switch(k)
{
case 1:
{
cout<<"请输入要排序的序列(以0结束输入):";
m=0;
while(1)
{
cin>>m1;
if(!m1) break;
else a[m++]=m1;
}
cout<<" 请按编号选择所需排序算法 "<<endl;
cout<<" 1:插入排序 "<<endl;
cout<<" 2:快速排序 "<<endl;
cout<<" 3:归并排序 "<<endl;
cout<<" 4:堆排序 "<<endl;
cout<<" 5:退出 "<<endl;
cout<<"排序之前的序列为:"<<endl;
for(i=0;i<m;i++)
{
b[i]=a[i];
cout<<a[i]<<" ";
}
cout<<endl;
while(1)
{
cout<<"请输入编号选择排序算法: ";
while(1)
{
cin>>k;
if(k<1||k>5)
cout<<"输入有误!请重新输入: ";
else
break;
}
flag2=0;
switch(k)
{
case 1://插入排序
for(i=0;i<m;i++)
a[i]=b[i];
insertionsort(a,0,m-1);
cout<<"经过插入排序后的序列为: "<<endl;
for(i=0;i<m;i++)
cout<<a[i]<<" ";
cout<<endl;
break;
case 2://快排
for(i=0;i<m;i++)
a[i]=b[i];
quicksort(a,0,m-1);
cout<<"经过快速排序后的序列为: "<<endl;
for(i=0;i<m;i++)
cout<<a[i]<<" ";
cout<<endl;
break;
case 3://归并排序
for(i=0;i<m;i++)
a[i]=b[i];
mergesort(c,a,0,m-1);
cout<<"经过归并排序后的序列为: "<<endl;
for(i=0;i<m;i++)
cout<<a[i]<<" ";
cout<<endl;
break;
case 4://堆排序
for(i=0;i<m;i++)
a[i]=b[i];
heapsort(a,m);
cout<<"经过堆排序后的序列为: "<<endl;
for(i=0;i<m;i++)
cout<<a[i]<<" ";
cout<<endl;
break;
case 5:
cout<<"您确认退出此项功能吗?(y/n): ";
while(1)
{
cin>>ch;
if(ch!='y'&&ch!='n')
cout<<"输入错误!请输入y/n进行选择: ";
else
break;
}
if(ch=='y')
{
flag2=1;
break;
}
}
if(flag2) break;
}
cout<<endl;
cout<<"按任意键返回主菜单 ";
getchar(); getchar();
system("cls");
break;
}
case 2:
{
srand(time(NULL));
for(i=0;i<10000;i++)
{
a[i]=rand()%10000;
b[i]=a[i];
}
cout<<" 以下为各种排序算法对同一个由一万个随机数组成的序列进行百次排序"<<endl;
cout<<" 在各自最好与最坏的情况下排序所花费的时间: "<<endl<<endl;
cout<<" 排序算法 最好情况所花时间(/s) 最坏情况所花时间(/s) "<<endl;
//插入排序部分
cout<<" 插入排序 ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
sort(a,a+10000);//最好情况为正序
start=clock(); //计时模块
insertionsort(a,0,9999);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f",totaltime);
cout<<" ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
sort(a,a+10000,cmp);//最坏情况为倒序
start=clock();
insertionsort(a,0,9999);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);;
//快速排序部分
cout<<" 快速排序 ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
start=clock();
quicksort(a,0,9999);//最好情况不清楚
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f",totaltime);
cout<<" ";
totaltime=0; t=10;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
sort(a,a+10000,cmp);//在用最后一个元素做基准元素时,有序是最坏的情况
start=clock();
quicksort(a,0,9999);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);;
//归并排序部分
cout<<" 归并排序 ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
start=clock();
mergesort(c,a,0,9999);//最好情况不清楚
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f",totaltime);
cout<<" ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
start=clock();
mergesort(c,a,0,9999);//最坏情况不清楚
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);;
//堆排序部分
cout<<" 堆排序 ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
sort(a,a+10000);//最好情况为初始非降序
start=clock();
heapsort(a,10000);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f",totaltime);
cout<<" ";
totaltime=0; t=100;
while(t--)
{
for(i=0;i<10000;i++)
a[i]=b[i];
start=clock();
heapsort(a,10000);//最坏情况不清楚
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);
cout<<endl;
cout<<"按任意键返回主菜单 ";
getchar(); getchar();
system("cls");
break;
}
case 3:
{
cout<<" 生成N个随机数的序列,并输出它们在不同算法下"<<endl;
cout<<" 进行1000次排序所花费的时间(输入0时退出此项功能)"<<endl<<endl;
cout<<" 排序算法 1000次排序所花时间(/s)"<<endl;
while(1)
{
int t,max; t=T;
cout<<"N=:";
cin>>N; max=N+100;
if(!N) break;
srand(time(NULL));
for(i=0;i<N;i++)
{
a[i]=rand()%max;
b[i]=a[i];
}
//插入排序部分
totaltime=0;
cout<<" 插入排序 ";
while(t--)
{
for(i=0;i<N;i++)
a[i]=b[i];
start=clock();
insertionsort(a,0,N-1);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);
//快速排序部分
totaltime=0;
cout<<" 快速排序 ";
t=T;
while(t--)
{
for(i=0;i<N;i++)
a[i]=b[i];
start=clock();
quicksort(a,0,N-1);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);
//归并排序部分
totaltime=0;
cout<<" 归并排序 ";
t=T;
while(t--)
{
for(i=0;i<N;i++)
a[i]=b[i];
start=clock();
mergesort(c,a,0,N-1);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);;
//堆排序部分
totaltime=0;
cout<<" 堆排序 ";
t=T;
while(t--)
{
for(i=0;i<N;i++)
a[i]=b[i];
start=clock();
mergesort(c,a,0,N-1);
finish=clock();
totaltime=totaltime+(double)(finish-start)/CLOCKS_PER_SEC;
}
printf("%.4f\n",totaltime);
}
cout<<endl;
cout<<"按任意键返回主菜单 ";
getchar(); getchar();
system("cls");
break;
}
case 4:
cout<<"您确认退出此项功能吗?(y/n): ";
while(1)
{
cin>>ch;
if(ch!='y'&&ch!='n')
cout<<"输入错误!请输入y/n进行选择: ";
else
break;
}
if(ch=='y')
{
flag1=1;
break;
}
}
system("cls");
if(flag1) break;
}
return 0;
}