排序算法的比较(随机化快速排序)
给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。
各组测试数据特点如下:
数据1:只有$1$个元素;
数据2:$11$个不相同的整数,测试基本正确性;
数据3:$10^3$个随机整数;
数据4:$10^4$个随机整数;
数据5:$10^5$个随机整数;
数据6:$10^5$个顺序整数;
数据7:$10^5$个逆序整数;
数据8:$10^5$个基本有序的整数;
数据9:$10^5$个随机正整数,每个数字不超过$1000$。
输入格式:
输入第一行给出正整数N(≤$10^5$),随后一行给出$N$个(长整型范围内的)整数,其间以空格分隔。
输出格式:
在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。
输入样例:
1 | 11 |
输出样例:
1 | -20 -17 -5 0 4 8 10 29 43 50 981 |
Source Code (C Language)
Quick Sort
1 |
|
快速排序有着众所周知的缺点:如果在算法的每一层递归上,划分都是最大程度不平衡的,那么算法的时间复杂度就是O(n^2)。也就是说,在最坏情况下,快速排序算法的运行时间并不比插入排序更好,此外,当输入数组完全有序时,快速排序的时间复杂度仍然为O(n^2).
Randomized Quick Sort
快速排序对于有顺序的数字序列表现较差,参考《算法导论》对快速排序进行优化,即快速排序的随机化版本如下:通过显式地对输入进行重新排列,使得算法实现随机化。具体思路为将主元(一般为数组末尾的数字)与数组中随机一个数字进行交换,这样保证了主元是随机选取的。
与上文快速排序相比仅两处改动
1 |
|
对比标准快速排序,对有序数组的效率有了极大的提升。
Heap Sort
1 |
|
Merge Sort
1 |
|
Insertion Sort
1 |
|
Bubble Sort
1 |
|
总结
对于以上六种排序算法的耗时统计如下表:(单位:ms)
测试点 \ 排序算法 | 快排 | 随机快排 | 归并 | 堆排 | 插入 | 冒泡 |
---|---|---|---|---|---|---|
0:只有1个元素 | 1 | 2 | 2 | 1 | 1 | 1 |
1:11个不相同的整数,测试基本正确性 | 1 | 2 | 2 | 1 | 1 | 1 |
2:10^3个随机整数 | 2 | 2 | 2 | 2 | 3 | 3 |
3:10^4个随机整数 | 4 | 4 | 7 | 6 | 29 | 170 |
4:10^5个随机整数 | 27 | 28 | 52 | 52 | 1829 | >10000 |
5:10^5个顺序整数 | 5376 | 45 | 44 | 47 | 29 | 5181 |
6:10^5个逆序整数 | 4462 | 41 | 43 | 47 | 3771 | >10000 |
7:10^5个基本有序的整数 | 5060 | 42 | 44 | 48 | 36 | 5102 |
8:10^5个随机正整数,每个数字不超过1000 | 28 | 31 | 48 | 48 | 1829 | >10000 |
对于以上六种排序算法的内存占用统计如下表:(单位:KB)
测试点 \ 排序算法 | 快排 | 随机快排 | 归并 | 堆排 | 插入 | 冒泡 |
---|---|---|---|---|---|---|
0:只有1个元素 | 228 | 384 | 196 | 384 | 256 | 384 |
1:11个不相同的整数,测试基本正确性 | 224 | 380 | 296 | 256 | 256 | 368 |
2:10^3个随机整数 | 360 | 228 | 364 | 384 | 288 | 296 |
3:10^4个随机整数 | 352 | 384 | 384 | 408 | 384 | 384 |
4:10^5个随机整数 | 1664 | 1664 | 2304 | 1664 | 1612 | - |
5:10^5个顺序整数 | 6340 | 1664 | 2304 | 1636 | 1696 | 1596 |
6:10^5个逆序整数 | 3928 | 1536 | 2404 | 1704 | 1664 | - |
7:10^5个基本有序的整数 | 6048 | 1636 | 2432 | 1704 | 1664 | 1592 |
8:10^5个随机正整数,每个数字不超过1000 | 1440 | 1496 | 2148 | 1408 | 1440 | - |