实验目的
(1)插入排序、合并、快速排序运行时间与排序元素个数的统计比较;
(2)阐述比较结果。
(3)利用算法采用的设计方法,时间复杂度等分析得到该结果的原因。
实验内容
//插入排序代码:
void InsertionSort(int r[], int n)
{
int i,j;
for(i=1;i<n;i++)
{
int temp;
j=i-1;
temp=r[i];
while(temp<r[j])
{
r[j+1]=r[j];
j--;
}
r[j+1]=temp;
}
}
//合并排序代码:
void Merge(int*a,int*b,int*c,int len_b,int len_c,int len)
{
int i=0;
int j=0;
int k=0;
while(i<len_b&&j<len_c)
{
if(b[i]<=c[j])
{
a[k]=b[i];
i+=1;
}
else
{
a[k]=c[j];
j+=1;
}
k+=1;
if(i==len_b)
memcpy(a+k,c+j,(len-k)*sizeof(int));
else
memcpy(a+k,b+i,(len-k)*sizeof(int));
}
}
void MergeSort(int *a,int len)
{
if (len==1)
return;
int len_b=len/2;
int len_c=len-len_b;
int *temp=(int*)malloc(sizeof(int)*len);
if(temp==NULL)
{
printf("malloc faild\n");
return;
}
memcpy(temp,a,len*sizeof(int));
int*b=temp;
int*c=temp+len_b;
MergeSort(b,len_b);
MergeSort(c,len_c);
Merge(a,b,c,len_b,len_c,len);
free(temp);
}
//快速排序;
void swap(int* a, int* b) {
int t = *a;
*a = *b;
*b = t;
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
//主函数:
int main()
{
int n;
printf("请输入n的值:");
scanf("%d",&n);
int arr[n];
srand(time(NULL));
for (int i = 0; i < n; i++) {
arr[i] = rand() % 300;
}
clock_t start1, end1;
start1 = clock();
InsertionSort(arr, n);
end1 = clock();
printf("直接插入排序运行时间:%f秒\n", (double)(end1 - start1) / CLOCKS_PER_SEC);
clock_t start2, end2;
start2= clock();
MergeSort(arr, n - 1);
end2 = clock();
printf("合并排序运行时间:%f秒\n", (double)(end2 - start2) / CLOCKS_PER_SEC);
start3= clock();
quickSort(arr, 0, n - 1);
end3 = clock();
printf("快速排序运行时间:%f秒\n", (double)(end3- start3) / CLOCKS_PER_SEC);
return 0;
}
实验结果:
由运行结果可视化分析可以得出,当n逐渐增大后,直接插入排序所花费的时间明显高于合并排序和快速排序的时间。
原因分析:
1.合并排序
合并排序的时间复杂度为O(nlogn),将长度为n的序列对半分割直到只有一个数据为止时,可以分成log2n行,因此,总共有log2n行,无论哪一行都是n个数据,所以每行的运行时间都为O(n),所以总的运行时间为O(nlog2n)/(nlogn)
2.插入排序:
取出来的的数字和左边已归位的数字进行比较,第一轮比较0次,第二轮比较1次,第三轮比较2次,第n轮要比较n-1次,所以总的比较次数为(n-1)+(n-2)+…+1≈n2/2,因此,插入排序的时间复杂度为O(n^2)。
3.快速排序:
快速排序的时间复杂度为O(nlgn)的原因是它采用了分治的思想,将一个大问题分解成多个小问题,然后递归地解决这些小问题。在快速排序的过程中,每次分区操作都会将一个元素放到它最终的位置上,因此每个元素最多只需要参与logn次分区操作,所以时间复杂度为O(nlogn)。
总结:综上所述,当面临小规模数据的排序时,插入排序是一个不错的选择;当面临大规模数据的排序时,合并排序和快速排序是更好的选择。在实际应用中,可以根据具体情况选择不同的排序算法。