原文链接:http://www.gbtags.com/gb/share/5592.htm
之前zhou--hua 分享了一个sort方法的详解,里面介绍了各种sort的方法,我觉得很有意义~一个好的开发还是需要知道一些重要的算法的。所以我就研究了二叉树BinaryTree
BinarySearchTree的好处是处理数据方便,包括插入,删除,排序,查找,都是很优的方法。
我们先来对比一下插入,删除,排序,查找,和其他的算法的复杂度:
1. 插入 ,对于每一个数据的插入来说,他的期望复杂度为O(log n),最差复杂度为O(n)。也就是说,一般他可以达到O(log n)的复杂度。当然,对于只是插入来说,这个复杂度很高,因为仅仅用array.push的复杂度为O(1)。但是这里的插入复杂度高的好处就是:降低了其他功能的复杂度
2.查找,如果要查找某一个数据是否存在,他的期望复杂度为O(log n),最差复杂度为O(n)。对于其他算法,一般对于无序的数组来说,最优解应该就是O(n),对于有序的数组来说,用binary search的复杂度为O(log n)。js内置方法indexOf,我没有找到这个方法的复杂度,但是我猜测应该也是O(n)。
3.排序,第一次排序,其实复杂的普遍认为是add和遍历加在一起,那么排序的复杂度就是O(n(log n)) + O(n) = O(n(log n)). 当add结束后,每次排序的复杂度为O(n),其实对于tree来说,他就是便利了一遍Tree。 对比其他的排序算法,像之前zhou--hua分享的sort文章中列出的几个算法,quickSort, mergeSort这几个常用的算法的复杂度都是O(n(log n)),相对于Tree来说,前面的两个算法的复杂度要高一些。
4.删除,他的期望复杂度为O(log n),最差复杂度为O(n)。相对于我们平时用的js删除方法,用arr.splice(arr.indexOf(item), 1);来比较,如果按照我的猜测indexOf的复杂度为O(n),那么这个东西的复杂度就至少为O(n)。所以,和Tree的删除比较,Tree的方法确实更快一点。
BinarySearchTree的缺点就是:
1. 所有的数据你必须在刚开始一个一个的添加到tree中,而这个过程的复杂度为O(n(log n)),因为你需要遍历整个数据O(n),然后一个一个加进去O(log n)。
2. 同时用Tree来存储肯定增大了原来的数据占的空间,因为你还需要定义left, right, root这些东西
3. 对于BinarySearchTree是不能有数据重复的。
4.数据最好是无序的,如果拿到的数据是有序的,那么上面的方法用的都是最差复杂度
但是,瑕不掩瑜,如果你写代码的时候,需要处理大量的数据,同时需要用到插入,查找,排序,删除这些功能,那么就推荐使用BinarySearchTree。或者更进一步的其他进阶的Tree,比如AVLTree和RBTree。
github地址: https://github.com/nzakas/computer-science-in-javascript/blob/master/data-structures/binary-search-tree/binary-search-tree.js
下面放上代码对比,为了让时间比较明显,其中add, search, delete都是处理一万条数据。sort是导出一个一万条排序好的array。按照zhou-hua的提醒,add和sort应该放到一起比较:(由于数据量比较大,所以刚打开的时候,浏览器会卡死一段时间)