vEB tree算法简介
vEB tree是VAN EMDE BOAS Tress的缩写,是一种 时间复杂度为O(lglgU) 的查找算法。基于比较操作的查找算法最佳时间复杂度为O(lgn),vEB tree算法借用了一些 位操作 的技巧,将时间复杂度降低为O(lglgn),所以在问题规模相对问题空间较大的情况下有较好的表现。它是由一个荷兰计算机学家Peter van Emde Boas领导的团队在1975年发明的。参考文献如下,如果链接过期了的话也可以根据论文名字重新搜索。
van Emde Boas, Peter. “Preserving order in a forest in less than logarithmic time.” 16th Annual Symposium on Foundations of Computer Science (sfcs 1975). IEEE, 1975.
另外作者在1977年改进了算法,将空间复杂度降低为线性,参考文献如下。
van Emde Boas, Peter. “Preserving order in a forest in less than logarithmic time and linear space.” Information processing letters 6.3 (1977): 80-82.
引子:传统的二分查找
问题:
给定一个递增的序列x[n],用二分查找数值a是否存在序列当中。
解答:
- 取序列二分点的数值和a对比,如果二分点的数值等于a,或序列长度为1则结束。
- 如果二分点大于a,则去掉序列后半段,否则去点序列前半段,返回1步。
以上就是典型的二分查找,每次都把序列对半分,直到序列长度为1,最坏的情况下可能操作x次。即:
$$n(\frac{1}{2})^x=1$$
显然:
$$x=log_2^n$$
接下来思考一个问题, 如果每次不是二分,而是多分 是不是可以算的更快呢?
vEB tree算法
数据存储在计算机当中是二进制的,计算机对数据的运算最终都是执行一些位操作。如果考虑位操作的话,其实每次是可以将数据$\sqrt n$分的。考虑数字16,可以分解为4x4,4是 $2^2$二进制是0B 100,16是$2^4$二进制表示l是0B 10000,刚好是0B 100乘方的结果。
假设有为0-15,共16个数,那么把这16个数全部用二进制表示如下:
D | 00 | 01 | 02 | 03 |
---|---|---|---|---|
B | 00 00 | 00 01 | 00 10 | 00 11 |
D | 04 | 05 | 06 | 07 |
B | 01 00 | 01 01 | 01 10 | 01 11 |
D | 08 | 09 | 10 | 11 |
B | 10 00 | 10 01 | 10 10 | 10 11 |
D | 12 | 13 | 14 | 15 |
B | 11 00 | 11 01 | 11 10 | 11 11 |
可以看到如果把二进制表示的数前后各两个比特位拆开,前两个比特位相同的数字合为一段,可以把大小为16的空间拆分成$\sqrt16$即4段。后两个比特位则可以表示数字在段当中的位置。比如数字9,拆分后,属于0B 10段,在段中的0B 01位。
另外再说明一下问题空间U和问题规模n,如上述例子,所有的数都在0-15范围内,问题空间U就是16。假设查找其中的2、4、11,三个数,问题规模n就是3。
现在vEB tree的核心思想就可以理解了,将要查找的数据按照二进制对半分(高位补零),前半部分为段值,后半部分为段内的位置。再段内位置作为问题空间递归的查找下去,直到找到或者问题空间大小为2为止。
举个例子,问题空间为256,查找数字7。二进制7为0B 0000 0111(高位补零),首次查找在0B 0000段,段内0B 0111位置。将段内位置作为问题空间递归查找,二次查找在0B 01段,段内0B 11位置。三次查找,在0B 1段,段内0B 1位置。查找结束。
以上就是最朴素的vEB tree思想的查找方法,每次都把问题空间开方分,直到问题空间为2,最坏的情况下可能操作x次。即:
$$U^{\frac{1}{2^x}}=2$$
显然:
$$x=log_2^{log_2^U}$$
vEB tree的数据结构
vEB tree是递归定义的,所以实际上vEB tree的数据结构很简单,只需要理解一个节点就可以了。
一个节点就是一个$\sqrt U$叉树,每个分支就是一个段,分支的值是一个指针,指向下一级节点。
每个节点包含两个特殊变量,最大值和最小值,表示这个节点以及它之下子节点存储的值当中的最大和最小值,如果是负数,则表示这个节点是空节点。
节点{
最大值
最小值
子节点1
…
子节点n
}
以上就是vEB tree的基本思想,更详细的介绍可以参考机械工业出版社的《算法导论》。
vEB tree的基本操作时间复杂度都是O(lglgU),所以对于在问题空间当中分布密集的数据有很好的表现。不过由于关键字限制在0-U之间,所以实际应用范围有限。
另外现在看起来vEB tree的空间复杂度是O(U),实际上通过哈希,可以降低到O(n)。