强烈建议您充分了解Proto Van Emde Boas树。
Van Emde Boas Tree支持O(lglgN)时间的搜索,后继,前任,插入和删除操作,这比任何相关数据结构(例如优先级队列,二进制搜索树等)都要快。Van Emde Boas Tree可与O(1)一起使用最小和最大查询的时间复杂度。在此,N是定义树的Universe的大小,而lg是对数基数2。
注意: Van Emde Boas数据结构的密钥集必须在0到n的范围内定义(n是2 k的正整数),并且在不允许重复的密钥时可以使用。
缩略语:
- VEB是Van Emde Boas树的缩写。
- VEB( )是VEB的缩写,包含u个键。
Van Emde Boas树的结构:
Van Emde Boas树是一个递归定义的结构。
- u :VEB树中存在的密钥数。
- 最小:包含在VEB树中的最小密钥。
- 最大值:包含VEB树中存在的最大密钥。
- 摘要:指向新VEB( )树,其中包含clusters数组中存在的键的概述。
- 簇:大小数组数组中的每个位置都指向新的VEB( ) 树。
参见下图以了解Van Emde Boas Tree的基础知识,尽管它并不代表Van Emde Boas Tree的实际结构:
对Van Emde Boas树的基本了解:
- Van Emde Boas树是递归定义的结构,类似于Proto Van Emde Boas树。
- 在Van Emde Boas树中,由于Van Emde Boas树存储树结构中存在的Minimum和Maximum键,因此最小和最大查询将在O(1)时间内工作。
- 添加“最大”和“最小”属性的优点,这有助于降低时间复杂度:
- 如果VEB树的最小值和最大值中的任何一个为空(代码中为NIL或-1),则树中不存在任何元素。
- 如果最小值和最大值相等,则结构中仅存在一个值。
- 如果两者都存在且不同,则树中将存在两个或多个元素。
- 我们可以通过在恒定时间(O(1))中根据条件设置最大值和最小值来插入和删除密钥,这有助于减少递归调用链:如果VEB中仅存在一个密钥,则只需设置该密钥即可删除该密钥最小和最大为nil值。同样,如果不存在键,则只需将min和max设置为要插入的键即可插入。这些是O(1)操作。
- 在后续查询和先前查询中,我们可以根据VEB的最小值和最大值进行决策,这将使我们的工作更加轻松。
在Pro Van Vande Boas树中,宇宙大小的大小被限制为2 2 k类型,但是在Van Emde Boas树中,它允许宇宙大小精确地为2的幂。因此,我们需要修改Proto Van Emde Boas树中使用的High(x),low(x),generate_index()帮助器函数,如下所示。
- 高(x):它将返回下限(x / ceil( )),基本上是其中存在键x的聚簇索引。
高(x)=底线(x / ceil( ))
- 低(x):它将返回x mod ceil( ),即其在集群中的位置。
低(x)= x%ceil( )
- generate_index(a,b):它将从键在簇b中的位置及其簇索引a返回键的位置。
generate_index(a,b)= a * ceil( )+ b
Van Emde Boas树的构造:Van Emde Boas树的构造与Proto Van Emde Boas树的构造非常相似。此处的区别在于,我们允许Universe的大小为2的任意幂,因此high(),low(),generate_index()会有所不同。
要构造空的VEB:步骤与Proto VEB相同,只是在每个VEB中添加了最小和最大两项。为了表示最小值和最大值为零,我们将其表示为-1。
注意:在基本情况下,我们只需要最小值和最大值,因为在添加最小值和最大值之后,添加大小为2的簇将是多余的。
下面是实现:
// C++ implementation of the approach #include
using namespace std; class Van_Emde_Boas { public: int universe_size; int minimum; int maximum; Van_Emde_Boas* summary; vector clusters; // Function to return cluster numbers // in which key is present int high(int x) { int div = ceil(sqrt(universe_size)); return x / div; } // Function to return position of x in cluster int low(int x) { int mod = ceil(sqrt(universe_size)); return x % mod; } // Function to return the index from // cluster number and position int generate_index(int x, int y) { int ru = ceil(sqrt(universe_size)); return x * ru + y; } // Constructor Van_Emde_Boas(int size) { universe_size = size; minimum = -1; maximum = -1; // Base case if (size <= 2) { summary = nullptr; clusters = vector (0, nullptr); } else { int no_clusters = ceil(sqrt(size)); // Assigning VEB(sqrt(u)) to summary summary = new Van_Emde_Boas(no_clusters); // Creating array of VEB Tree pointers of size sqrt(u) clusters = vector (no_clusters, nullptr); // Assigning VEB(sqrt(u)) to all of its clusters for (int i = 0; i < no_clusters; i++) { clusters[i] = new Van_Emde_Boas(ceil(sqrt(size))); } } } }; // Driver code int main() { // New Van_Emde_Boas tree with u = 16 Van_Emde_Boas* akp = new Van_Emde_Boas(4); }