目录
1.课题要求
设计程序,利用随机函数产生20000个随机整数(1~100000), 完成下面功能:
(1)对这些数分别进行直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序2-路归并排序、链式基数排序,并把排序结果保存到文件中。
(2) 分析上述排序算法的性能(以运行程序所花费的时间为准进行对比),找出较快的排序方法。
(3)计算并输出所选排序算法中比较的次数和数据移动的次数。
(4)若排序的整数增加到100000个、100000000个,排序结果有什么变化,请分析并验证。
2.课题分析
这一课题主要考查我们对所有排序方法的应用,10大经典排序的互相结合,本质并不难,首先,先简单地介绍一下10大经典排序。
(1)冒泡排序
冒泡排序是我们最早接触编程的时候所接触的第一个排序方法,它的时间复杂度最坏为O(n2),又称为"沉底法",每次交换相邻的两个位置,如果前面的数比后面的数大,那么就交换他们,迭代n-1次就可以确定每一个数的位置。
i∈[0,N-1) //循环N-1遍
j∈[0,N-1-i) //每遍循环要处理的无序部分
swap(j,j+1) //两两排序(升序/降序)
(2)选择排序
选择排序也是我们常用的排序方法,每次都从无序区中选择一个最小的数放在有序区的相应的位置。
for(int i=1;i<=n-1;i++) //n-1趟
{
int min=i;
for(int j=i+1;j<=n;j++)//每次从当前位置向后找无序区中一个最小的值
if(q[j]<q[min]) min=j;
swap(q[i],q[min]);
}
(3)快速排序
有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)
(4)归并排序
有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)
(5)堆排序
有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)
(6)直接插入排序
和选择排序的思路大致相同,但是不同的是直接插入排序是依次从无序区中选择一个数,然后通过在有序区中进行比较找到相应的位置,而选择排序每次则是总无序区中找到一个最小值,直接插入有序区的后面即可。
for(int i=2;i<=n;i++)
if(q[i]<q[i-1])
{
int temp=q[i],j;
for(j=i-1;j>=1&&temp<q[j];j--) q[j+1]=q[j];
q[j+1]=temp;
}
(7)折半插入排序
对直接插入排序的优化,每次在有序区用二分法找到相应的位置。
void mid_sort(int q[],int n)
{
for(int i=2;i<=n;i++)
{
q[0]=q[i];
int l=1,r=i-1;
while(l<=r)
{
int mid=l+(r-l)/2;
if(q[mid]>q[0]) r=mid-1;
else l=mid+1;
}
for(int j=i-1;j>=r+1;--j)
q[j+1]=q[j];
q[r+1]=q[0];
}
}
(8)希尔排序
找到一个增量,每次对增量区间进行排序,如1,3,5/2,4,6
void shell_sort(int q[],int n)
{
int j=n;
while(j>1)
{
j=j/3+1;
for(int i=1;i<=n-j;i++)
{
int r=i,t=q[r+j];
while(r>=1)
if(t<q[r]) q[r+j]=q[r],r-=j;
else break;
q[r+j]=t;
}
}
}
(9)桶排序
把数分成多个桶,如10~15内的数是一个桶,16~20......,每次对桶内元素进行排序,最后合并桶。
void bucket_sort(int q[],int n)
{
int min=INF,max=-INF;
for(int i=1;i<=n;i++)
{
if(q[i]<min) min=q[i];
if(q[i]>max) max=q[i];
}
int count=(max-min)/n+1;
vector<vector<int>> a;//大桶
for(int i=1;i<=count;i++)
{
vector<int> b;
a.push_back(b);//每个小桶
}
for(int i=1;i<=n;i++)
{
int num=(q[i]-min)/n;
a[num].push_back(q[i]);
}
for(int i=0;i<count;i++) sort(a[i].begin(),a[i].end());
int k=1;
for(int i=0;i<count;i++)
for(int j=0;j<a[i].size();j++)
q[k++]=a[i][j];
}
3.源代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stdlib.h>
using namespace std;
const int N=1e6+10,INF=0x3f;
int q[N];
int tmp[N];
int n;
int siz;
//快速排序
void quick_sort(int q[],int l,int r)
{
if(l>=r) return ;
int x=q[l+r>>1],i=l-1,j=r+1;
while(i<j)
{
do i++;while(q[i]<x);
do j--;while(q[j]>x);
if(i<j) swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
//归并排序
void merge_sort(int q[],int l,int r)
{
if(l>=r) return ;
int mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r)
if(q[i]<q[j]) tmp[k++] = q[i++];
else tmp[k++] = q[j++];
while(i<=mid ) tmp[k++] = q[i++];
while(j<=r) tmp[k++] = q[j++];
for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
//直接插入排序
void insert_sort(int q[],int n)
{
for(int i=2;i<=n;i++)
if(q[i]<q[i-1])
{
int temp=q[i],j;
for(j=i-1;j>=1&&temp<q[j];j--) q[j+1]=q[j];
q[j+1]=temp;
}
}
//冒泡排序
void down_sort(int q[],int n)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n-i;j++)
if(q[j]>q[j+1]) swap(q[j],q[j+1]);
}
void down(int u)
{
int t=u;
if(2*u<=siz&&q[2*u]<q[t]) t=2*u;
if(2*u+1<=siz&&q[2*u+1]<q[t]) t=2*u+1;
if(t!=u)
{
swap(q[t],q[u]);
down(t);
}
}
//堆排序
void heap_sort(int q[],int n)
{
siz=n;
for(int i=n/2;i>=1;i--) down(i);
printf("排序后的结果为:");
for(int i=1;i<=n;i++)
{
cout<<q[1]<<" ";
q[1]=q[siz];
siz--;
down(1);
}
}
//折半插入排序
void mid_sort(int q[],int n)
{
for(int i=2;i<=n;i++)
{
q[0]=q[i];
int l=1,r=i-1;
while(l<=r)
{
int mid=l+(r-l)/2;
if(q[mid]>q[0]) r=mid-1;
else l=mid+1;
}
for(int j=i-1;j>=r+1;--j)
q[j+1]=q[j];
q[r+1]=q[0];
}
}
//希尔排序
void shell_sort(int q[],int n)
{
int j=n;
while(j>1)
{
j=j/3+1;
for(int i=1;i<=n-j;i++)
{
int r=i,t=q[r+j];
while(r>=1)
if(t<q[r]) q[r+j]=q[r],r-=j;
else break;
q[r+j]=t;
}
}
}
//简单选择排序
void select_sort(int q[],int n)
{
for(int i=1;i<=n-1;i++) //n-1趟
{
int min=i;
for(int j=i+1;j<=n;j++)//每次从当前位置向后找一个最小的值
if(q[j]<q[min]) min=j;
swap(q[i],q[min]);
}
}
//桶排序
void bucket_sort(int q[],int n)
{
int min=INF,max=-INF;
for(int i=1;i<=n;i++)
{
if(q[i]<min) min=q[i];
if(q[i]>max) max=q[i];
}
int count=(max-min)/n+1;
vector<vector<int>> a;//大桶
for(int i=1;i<=count;i++)
{
vector<int> b;
a.push_back(b);//每个小桶
}
for(int i=1;i<=n;i++)
{
int num=(q[i]-min)/n;
a[num].push_back(q[i]);
}
for(int i=0;i<count;i++) sort(a[i].begin(),a[i].end());
int k=1;
for(int i=0;i<count;i++)
for(int j=0;j<a[i].size();j++)
q[k++]=a[i][j];
}
void print()
{
for(int i=1;i<=n;i++) cout<<q[i]<<" ";
}
void menu()
{
puts("**********排序综合问题**********");
puts("**********1.快速排序 **********");
puts("**********2.归并排序 **********");
puts("**********3.直接插入排序*********");
puts("**********4.冒泡排序 **********");
puts("**********5.堆排序 **********");
puts("**********6.折半插入排序*********");
puts("**********7.希尔排序 **********");
puts("**********8.简单选择排序**********");
puts("**********9.桶排序 ***********");
}
int main()
{
while(1)
{
cout<<"请输入个数:";
scanf("%d",&n);
printf("请输入%d个数:",n);
for(int i=1;i<=n;i++) scanf("%d",&q[i]);
menu();
cout<<"请输入一个序号:";
int op;
cin>>op;
if(op==1)
{
quick_sort(q,1,n);
printf("排序后的结果为:");
print();
}
else if(op==2)
{
merge_sort(q,1,n);
printf("排序后的结果为:");
print();
}
else if(op==3)
{
insert_sort(q,n);
printf("排序后的结果为:");
print();
}
else if(op==4)
{
down_sort(q,n);
printf("排序后的结果为:");
print();
}
else if(op==5)
{
heap_sort(q,n);
}
else if(op==6)
{
mid_sort(q,n);
printf("排序后的结果为:");
print();
}
else if(op==7)
{
shell_sort(q,n);
printf("排序后的结果为:");
print();
}
else if(op==8)
{
select_sort(q,n);
printf("排序后的结果为:");
print();
}
else if(op==9)
{
bucket_sort(q,n);
printf("排序后的结果为:");
print();
}
else printf("序号错误!\n");
puts("");
system("pause");
system("cls");
}
return 0;
}