小白学算法2.A——常见排序算法比较
标签: 小白学算法 博客
1.常见算法的时间复杂度与空间复杂度
名称 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|
冒泡排序 | O(N2) | O(N2) | O(1) | 稳定 |
选择排序 | O(N2) | O(N2) | O(1) | 不稳定 |
插入排序 | O(N2) | O(N2) | O(1) | 稳定 |
希尔排序 | O(N1.5) | O(N2) | O(1) | 不稳定 |
归并排序 | O(NlogN) | O(NlogN) | O(N) | 稳定 |
快速排序 | O(NlogN) | O(N2) | O(logN) ~ O(N) | 不稳定 |
堆排序 | O(NlogN) | O(NlogN) | O(1) | 不稳定 |
关于各种排序如何实现请阅读:小白学算法
2.实际数据排序比较
本博文将采用牛刀小试(02)——生成不重复的随机数中的方法生成的50000个不重复的随机序列作为测试数据。每种排序方法为小白学算法中实现的各种算法。测试主函数如下:
int main()
{
DWORD time[7] = {0};
BubbleSort bubbleSort;
SelectionSort selectionSort;
InsertionSort insertionSort;
ShellSort shellSort;
MergeSort mergeSort;
QuickSort quickSort;
HeapSort heapSort;
for (int i=0; i<10; i++)//为了提高准确性,每种排序运行10次
{
//所有排序函数返回运行的时间
time[0] += bubbleSort.bubbleSort();
time[1] += selectionSort.selectionSort();
time[2] += insertionSort.insertionSort();
time[3] += shellSort.shellSort();
time[4] += mergeSort.mergeSort();
time[5] += quickSort.quickSort();
time[6] += heapSort.heapSort();
}
for (i=0; i<7; i++)
cout<<time[i]<<"ms"<<endl;
return 0;
}
单位:最快时间的倍数(相对时间)
模式 | 冒泡 | 选择 | 插入 | 希尔 | 归并 | 快排 | 堆排序 |
---|---|---|---|---|---|---|---|
Debug | 1939 | 56.42 | 1486 | 3.42 | 1 | 1.10 | 2.52 |
Release | 1273 | 284 | 392 | 2.03 | 2.52 | 1.03 | 1 |
3.总结
- 当数据量较小的时候,时间复杂度 O(N2) 和 O(NlogN) 运行的时间相差无几
- 当数据量较大的时候,时间复杂度 O(N2) 和 O(NlogN) 运行的时间相差就非常的明显,这个时候应当尽量使用高级算法
- 快速排序是最常使用的高级排序算法,两种测试模式下快排比最快的排序只慢一点点
- 一般STL中的sort算法就是插入排序和优化后快速排序结合而成。数据少时使用插入,数据多时使用快排;调用快排之前随机打乱数据以避免发生最坏情况;快排选择分界点元素也有一定的规则
- 归并排序最坏的情况下时间复杂度也是 O(NlogN) ,但是为什么应用不广泛呢?最大的限制就是空间复杂度为 O(NlogN) ,现在的数据都非常的多,排序1G的数据,占用2G的内存太不现实
- 堆排序也很快,限制堆排序的重要因素是堆排序不能够很好的利用现代计算机的缓存,无形之中增加了排序的时间
- 希尔排序的时间复杂度为 O(N1.5) ,处于高级算法和低级算法之间,常常用于嵌入式系统,因为嵌入式系统的数据一般不是很大,而且希尔排序编写起来方便
- 对排序算法进行选择的时候,一定要注意排序的结果要求是稳定还是不稳定
- 基础的排序算法都可以再进行优化,比如使用链表而不是数组