计算机的特点是擅长大量重复而简单的运算,人则是更擅长复杂的、抽象的、高视角的思维。
这个区别导致计算机程序解决问题的路数,与人的差异较大。
以排序为例子,人会首先选择最显眼的东西,最大的数字,导致逆序最多的数字,从而尽量移动最少的次数完成排序。
几个“最”,说明人对极值更敏感:(
电脑一般情况下,要么从头到尾遍历,要么使用二分法。
电脑算法的优化,很多就是把遍历算法变成二分法的递归。
冒泡排序,是假设第1个最小,然后依次与第2~N个比较,如果有比第1个更小的则交换到第1个的位置,继续比较。
排完了最小的,排第二小的,...,直到排完了第二大的,剩下的就是最大的。
典型的遍历算法,遍历两遍,复杂度为O(N^2)。
归并排序,则是典型的二分法。
16个数,一分为二每组8个,二分为4每组4个,三分为8每组2个,四分为16每组1个。
每组1个的时候也就无所谓顺序了。
然后把它们两两一组的合并起来,只需要一次比较,小的在前,大的在后,也就排好了。
然后依次递归处理,组的元素个数越来越多,组的个数越来越少,最终只剩下1个组,排序完成。
但是它有中间的临时数据,需要额外的存储空间:(
与归并排序类似的一个是,矩阵乘法的斯特拉森算法。
矩阵需要是2^N的方阵,如果不是则用0填成2^N的方阵。
只不过斯特拉森算法,不是二分法,而是四分法。
把1个大矩阵分成4个小矩阵,然后通过小矩阵之间的加减运算,把常规算法的8次小矩阵之间的乘法减少到7次。
这样在不断四分然后递归合并之后,复杂度就从O(N^log8),也就是O(N^3)变成了O(N^log7)。
斯特拉森算法也有中间矩阵的临时数据,而且对于小矩阵并不好用,因为CPU本身就有向量运算指令,例如ARM的NEON,intel的MMX等等。
斯特拉森的贡献,在于他第一个发现了矩阵乘法的运算复杂度可以化简。
在他之后,很快就有一堆低复杂度的算法跑了出来。
最后说说红黑树,它是一个平衡二叉树。二叉树可以二分查找,速度比链表快得多,但前提是它必须平衡,否则就是个大号的链表。
红黑树,就是一个平衡二叉树,算法细节比较复杂,可以看算法导论。
如果一个数据结构,需要频繁的增删改查,那么它就可以使用红黑树,不管添加、删除、查找的复杂度都是O(logN)。
典型应用是Linux系统的进程管理结构,Nginx服务器的定时器管理结构。