文章目录
前言
本文主要比较冒泡排序和快速排序的时间,并对冒泡排序进行了改良。
冒泡排序和快速排序的思想可以参考我转载的以下博文:
https://blog.csdn.net/gogo0707/article/details/124388314
代码设计
- 随机生成10000个随机数,进行冒泡排序和快速排序,并比较时间;
- 然后改良冒泡排序,再比较冒泡、改良后的冒泡、快排的时间
本设计中使用clock函数获取cpu运行时间,排序后的cpu clock数减去排序前的cpu clock数,就可以得到排序消耗的cpu clock数。
代码实现
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
//随机生成10000个随机数,进行冒泡排序和快速排序,并比较时间。
//冒泡排序
void BubbleSort(int *a, int length)
{
int temp;
for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - i - 1; j++)
{
if (a[j] > a[j + 1])
{
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
//快速排序
void QuickSort(int *arr, int low, int high)
{
if (low < high)
{
int i = low;
int j = high;
int k = arr[low];
while (i < j)
{
while (i < j && arr[j] >= k) // 从右向左找第一个小于k的数
{
j--;
}
if (i < j)
{
arr[i++] = arr[j];
}
while (i < j && arr[i] < k) // 从左向右找第一个大于等于k的数
{
i++;
}
if (i < j)
{
arr[j--] = arr[i];
}
}
arr[i] = k;
// 递归调用
QuickSort(arr, low, i - 1); // 排序k左边
QuickSort(arr, i + 1, high); // 排序k右边
}
}
//改良后的冒泡排序
void bubble_sort(int *array, int size)
{
int max;
int pos;
int i,j;
int tmp;
max = array[0];
pos = 0;
for(i = 0; i < size-1; i++) //循环一次就找到一个较大的数,然后与数组的第n个数据交换位置(n从0开始)
{
for(j = i; j <= size-1; j++)
{
if(array[j] > max)
{
max = array[j];
pos = j;
}
}
tmp = array[i];
array[i] = array[pos];
array[pos] = tmp;
max = array[i+1];
pos = i+1;
}
}
int main(void)
{
int num[10000];
srand(time(0));
for (int i = 0; i<10000; i++)
{
num[i] = rand() % 10000;
}
clock_t start = clock();
BubbleSort(num, 10000); //冒泡排序测试
clock_t end = clock();
printf("使用冒泡排序花费了 %ld cpu clock\n", (end - start));//<-
getchar();
for (int i = 0; i<10000; i++)
{
num[i] = rand() % 10000;
}
clock_t start2 = clock();
QuickSort(num, 0, 9999); //快排测试
clock_t end2 = clock();
printf("使用快速排序花费了 %ld cpu clock\n", (end2 - start2));//<-
getchar();
for (int i = 0; i<10000; i++)
{
num[i] = rand() % 10000;
}
clock_t start3 = clock();
bubble_sort(num, 10000); //改良之后的冒泡排序测试
clock_t end3 = clock();
printf("使用改良后的冒泡排序花费了 %ld cpu clock\n", (end3 - start3));//<-
getchar();
}
运行结果
结果分析
- 从运行结果可以看出,快速排序用时最短,冒泡排序用时最长,两者相差了几个数量级;
- 改良后的冒泡比传统的冒泡用时更短,有接近3倍的差距;
稳定性测试
做3个测试:
第1个测试,数组(有10000个数据)通过随机数产生,随机数的范围指定为0到9999;
第2个测试,数组(有10000个数据)通过随机数产生,随机数的范围指定为0到99;
第2个测试,数组(有10000个数据)通过随机数产生,随机数的范围指定为0到9;
观察并比较各排序算法用时的变化。
第一个测试结果如下:
算法 | 测试总次数 | 平时用时(clocks) |
---|---|---|
冒泡 | 10 | 144900 |
改良后冒泡 | 10 | 54629 |
快速排序 | 10 | 773 |
第二个测试结果如下:
算法 | 测试总次数 | 平时用时(clocks) |
---|---|---|
冒泡 | 10 | 159,981 |
改良后冒泡 | 10 | 54,835 |
快速排序 | 10 | 1,081 |
第三个测试结果如下:
算法 | 测试总次数 | 平时用时(clocks) |
---|---|---|
冒泡 | 10 | 149,306 |
改良后冒泡 | 10 | 54,233 |
快速排序 | 10 | 5,876 |
从测试结果可以计算出相差不同数量级(以第一个测试为基准)下各算法用时的变化率,如下表:
算法 | 相差2个数量级,排序时间的变化率 | 相差3个数量级,排序时间的变化率 |
---|---|---|
冒泡 | 10.41% | 3.04% |
改良后冒泡 | 0.38% | -0.72% |
快速排序 | 39.84% | 660.16% |
综上,可以发现待排序的数据的关联性对快速排序影响很大,排序时间波动很大,不稳定;
而冒泡排序受到的影响相对较小,排序时间比较稳定。
总结
快速排序虽然用时较短,但是压栈严重,容易造成堆栈溢出,稳定性较差。
冒泡排序虽然平均时间复杂度比较大,但是算法比较稳定。
以上测试的测试量不够大,只能体现出一些变化规律。