算法基础——大O表示法
最近在补算法基础,我们在学习算法时一定要熟悉三种数据结构:数组,链表,散列表
例如它们在Java中体现出来的是:ArrayList,LinkedList,HashMap.
它们可玩性很大了,但并不是我们主要目的,可以参考我之前写的一篇随笔:Java基础之集合
当你已经完全明白这三种数据结构后,你才算入门算法的门槛,并不要觉得这些很难,万事开头难,等你学完之后就知道了,就那么回事。
好了扯远了,所谓算法,是指你处理一件事情所用的方法,就例如张三砍树用电锯,你砍树用菜刀,好的算法让你事半功倍。
那么如何评价一个算法的好坏呢?我们用大O表示法,请看图:
大o表示法表格(增长率变化)
函数排序(越小越接近期望):
O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2^N)
函数 |
非正式术语 |
n=25 |
n=50 |
f(50)/f(25) |
100次最差执行次数 |
O(1) |
常数阶 |
1 |
1 |
1 |
1次 |
O(n) |
线性阶 |
25 |
50 |
2 |
100次 |
O(n log n) |
对数-线性阶 |
116 |
282 |
2.43 |
??? |
O(n²) |
平方阶 |
625 |
2500 |
4 |
100 00次 |
O(log n) |
对数阶 |
4.64 |
5.64 |
1.21 |
7次 |
O(n³) |
立方阶 |
15625 |
125000 |
8 |
100 00 00次 |
O(2^n) |
指数阶 |
3.36*10^7 |
1.27*10^15 |
3.35*10^7 |
??? |
算法中的大O法的呈现程度是"最差场景"的执行速度,而不是"最幸运"场景。
例如一个序列,它已经99%将近排序完成了,此时最快处理的算法是平常我们遇到最多的乱序场景下最慢的算法,所以根据场景的不同,各个算法的表现也各不相同,而我们选择的算法应该是应对"最坏"场景下的算法!
不同场景下不同算法的最佳排行:
1.乱序场景(Randm)
推荐:希尔,快排,(次)归并
2.大重复场景(Faw Unique)
推荐:快排,(次)希尔,归并,梳排,堆排,
3.全逆向场景(Reversed)
推荐:快排,希尔,(次)归并,堆排,梳排
4.99%近完成(Almost Sorted)
推荐:插排,鸡尾酒,(次)快排,希尔,梳排,归并
我们必须要记住那些算法?划重点!
排序算法 |
名称 |
平均复杂度 |
空间复杂度 |
最坏情况 |
最好情况 |
稳定性 |
冒泡排序 |
Bubble |
n² |
1 |
n² |
n |
稳定 |
选择排序 |
Selection |
n² |
1 |
n² |
n² |
不稳定 |
插入排序 |
Insertion |
n² |
1 |
n² |
n |
稳定 |
堆排序 |
heap |
n log2 n |
1 |
n log2 n |
n log2 n |
不稳定 |
归并排序 |
Merge |
n log2 n |
n |
n log2 n |
n log2 n |
稳定 |
希尔排序 |
Shell |
n1.3 |
1 |
n² |
n |
不稳定 |
快速排序 |
Quick |
n log2 n |
n² |
n² |
n log2 n |
不稳定 |
桶排序 |
Bucket |
n + k |
n + k |
n² |
n |
稳定 |
计数排序 |
Counting |
n + k |
n + k |
n + k |
n + k |
稳定 |
基数排序 |
Radix |
n * k |
n + k |
n * k |
n * k |
稳定 |
*最坏情况和最好情况并不需要特别强记,只需要记住平均复杂度就行。
通过大O表示法,我们可以清楚明了的知道算法的好坏,在最适合的场景选择最适合的算法!