VanEmdeBoas树的详细介绍见算法导论第三版,这里只给出实现

C++代码:

#include <iostream>
#include <memory>
#include <vector>
#include <deque>
#include <stack>
#include <random>
#include <ctime>
using namespace std;struct VanEmdeBoasTreeNode  //vEB树节点定义
{enum NodeType { SUMMARY, CLUSTER } node_type;  //节点类型unsigned int global_size; //注意,这里存储的是实际全域大小关于底数2的对数,不是全域大小本身unsigned long long* min = nullptr;  //节点最大值,不存在为nullptrunsigned long long* max = nullptr;  //节点最小值,不存在为nullptrVanEmdeBoasTreeNode* summary = nullptr;  //当前节点的summary节点指针vector<VanEmdeBoasTreeNode*> cluster;  //cluster子节点指针VanEmdeBoasTreeNode(unsigned int g, NodeType node_type) :global_size(g), node_type(node_type) {}~VanEmdeBoasTreeNode() { delete min; delete max; }
};unsigned long long low(VanEmdeBoasTreeNode* node, unsigned long long x)  //调用这三个函数时总是假定node的全域大小大于等于2,即node不是叶节点,low,high,index函数的详细定义见算法导论,这里使用移位运算加快求值速度
{unsigned int g = node->cluster[0]->global_size;unsigned long long full = 0xffffffffffffffff;full = full >> (64U - g);return x & full;
}unsigned long long high(VanEmdeBoasTreeNode* node, unsigned long long x)
{unsigned int g = node->cluster[0]->global_size;return x >> g;
}unsigned long long index(VanEmdeBoasTreeNode* node, unsigned long long low, unsigned long long high)
{unsigned int g = node->cluster[0]->global_size;high = high << g;return high | low;
}struct StackNode
{VanEmdeBoasTreeNode* cur;unsigned long long high;StackNode(VanEmdeBoasTreeNode* c, unsigned long long h) :cur(c), high(h) {}
};class VanEmdeBoasTree
{
public:enum class StyleOfCreatTree { BFS, DFS };  //建树方式,深度优先或广度优先VanEmdeBoasTree(StyleOfCreatTree how_building_tree, unsigned int g);  //g为全域大小,为实际全域大小关于底数2的对数shared_ptr<unsigned long long> min() { if (isEmpty()) return nullptr;  return make_shared<unsigned long long>(*root->min); }   //返回最小值shared_ptr<unsigned long long> max() { if (isEmpty()) return nullptr;  return make_shared<unsigned long long>(*root->max); }  //返回最大值bool remove(unsigned long long x) { if (beyondGlobalSize(x)) return false; return removeValue(root, x); }  //删除值bool insert(unsigned long long x) { if (beyondGlobalSize(x)) return false; return insertValue(root, x); }  //插入值bool contain(unsigned long long x) { if (beyondGlobalSize(x)) return false; return containValue(root, x); }  //判断值是否存在bool isEmpty() { return root->min == nullptr; }  //判断vEB树是否为空shared_ptr<unsigned long long> pre(unsigned long long x) { if (beyondGlobalSize(x)) return nullptr; return findPrecessor(root, x); }  //返回x前驱shared_ptr<unsigned long long> suc(unsigned long long x) { if (beyondGlobalSize(x)) return nullptr; return findSuccessor(root, x); }  //返回x后继void printValueInTreeFromSmallToLarge();    //从小到大打印vEB树中所有值void printValueInTreeFromLargeToSmall();    //从大到小打印vEB树中所有值~VanEmdeBoasTree();  //销毁vEB树
private:bool beyondGlobalSize(unsigned long long x);   //判断x是否超出实际全域大小bool removeValue(VanEmdeBoasTreeNode* root, unsigned long long x);bool insertValue(VanEmdeBoasTreeNode* root, unsigned long long x);bool containValue(VanEmdeBoasTreeNode* root, unsigned long long x);shared_ptr<unsigned long long> findPrecessor(VanEmdeBoasTreeNode* root, unsigned long long x);shared_ptr<unsigned long long> findSuccessor(VanEmdeBoasTreeNode* root, unsigned long long x);StyleOfCreatTree style_of_build_tree = StyleOfCreatTree::DFS;   //建树方式VanEmdeBoasTreeNode* root = nullptr;   //vEB树根节点
};void VanEmdeBoasTree::printValueInTreeFromLargeToSmall()
{cout << "从大到小打印树中值" << endl;shared_ptr<unsigned long long> p = max();if (p == nullptr){cout << "NULL";cout << endl;return;}while (p != nullptr){cout << *p << " ";p = pre(*p);}cout << endl;
}void VanEmdeBoasTree::printValueInTreeFromSmallToLarge()
{cout << "从小到大打印树中值" << endl;shared_ptr<unsigned long long> p = min();if (p == nullptr){cout << "NULL";cout << endl;return;}while (p != nullptr){cout << *p << " ";p = suc(*p);}cout << endl;
}bool VanEmdeBoasTree::beyondGlobalSize(unsigned long long x)
{unsigned int g = root->global_size;unsigned long long t = 0xffffffffffffffff;t = t >> (64U - g);if (0 <= x && x <= t){return false;}else{return true;}
}bool VanEmdeBoasTree::containValue(VanEmdeBoasTreeNode* root, unsigned long long x)
{VanEmdeBoasTreeNode* cur = root;unsigned long long cur_value = x;while (true){if (cur->min == nullptr)return false;if (cur_value == *cur->min)return true;if (*cur->min == *cur->max)return false;if (cur->summary == nullptr)return true;if (cur_value < *cur->min || cur_value >* cur->max)return false;if (cur_value == *cur->max)return true;VanEmdeBoasTreeNode* temp = cur->cluster[high(cur, cur_value)];   //下降到下一层递归搜索cur_value = low(cur, cur_value);cur = temp;}
}bool VanEmdeBoasTree::insertValue(VanEmdeBoasTreeNode* root, unsigned long long x)   //在以root为根的vEB树中插入x,true插入成功,false插入失败
{stack<StackNode> work_stack;VanEmdeBoasTreeNode* cur = root;unsigned long long cur_value = x;while (true){if (cur->min == nullptr)break;if (cur_value == *cur->min)return false;if (*cur->min == *cur->max)break;if (cur->summary == nullptr)return false;if (cur_value < *cur->min)  //应当在当前节点插入比最小值更小的值,此时用当前值更新最小值,并把原先的最小值调整为要插入值{unsigned long long temp = *cur->min;*cur->min = cur_value;cur_value = temp;}work_stack.push(StackNode(cur, high(cur, cur_value)));   //继续向下一层寻找插入位置VanEmdeBoasTreeNode* temp = cur->cluster[high(cur, cur_value)];cur_value = low(cur, cur_value);cur = temp;}if (cur->min == nullptr)        //在找到的插入位置插入{cur->min = new unsigned long long(cur_value);cur->max = new unsigned long long(cur_value);}else if (*cur->min == *cur->max){if (cur_value < *cur->min){*cur->min = cur_value;if (cur->summary != nullptr){unsigned long long high_pos = high(cur, *cur->max);unsigned long long value = low(cur, *cur->max);cur->cluster[high_pos]->max = new unsigned long long(value);cur->cluster[high_pos]->min = new unsigned long long(value);insertValue(cur->summary, high_pos);}}else{*cur->max = cur_value;if (cur->summary != nullptr){unsigned long long high_pos = high(cur, cur_value);unsigned long long value = low(cur, cur_value);cur->cluster[high_pos]->max = new unsigned long long(value);cur->cluster[high_pos]->min = new unsigned long long(value);insertValue(cur->summary, high_pos);}}}while (work_stack.empty() == false)   //自底向上调整summary和max值{cur = work_stack.top().cur;unsigned long long high = work_stack.top().high;work_stack.pop();cur_value = index(cur, cur_value, high);if (*cur->cluster[high]->min == *cur->cluster[high]->max)insertValue(cur->summary, high);if (cur_value <= * cur->max)        //如果当前层节点max值没有因插入而改变,则无需继续向上调整,直接退出return true;*cur->max = cur_value;}return true;
}bool VanEmdeBoasTree::removeValue(VanEmdeBoasTreeNode* root, unsigned long long x)   //在以root为根的vEB树中删除x,成功返回true,失败返回false
{stack<StackNode> work_stack;VanEmdeBoasTreeNode* cur = root;unsigned long long cur_value = x;while (true)    //从根节点向下搜索,找到叶节点或只含有单一值的分支节点且x在其中即退出,否则返回false{if (cur->summary == nullptr){if (cur->min == nullptr)return false;if (*cur->min == *cur->max){if (cur_value == *cur->min)break;return false;}break;}else{if (cur->min == nullptr)return false;if (cur_value == *cur->min){if (*cur->min == *cur->max)break;unsigned long long t = *cur->summary->min;  //这里相当关键,如果在一个包含两个或两个以上值的分支节点找到x且x恰为分支节点最小值cur_value = *cur->cluster[t]->min;          //则应用x在该节点的后继替换最小值,同时更改当前搜索值为替换后的新值,然后下降到x在当前节点的后继所在的当前节点的子vEB树继续搜索*cur->min = index(cur, cur_value, t);work_stack.push(StackNode(cur, t));cur = cur->cluster[t];continue;}if (*cur->min == *cur->max)return false;if (cur_value < *cur->min || cur_value >* cur->max)return false;work_stack.push(StackNode(cur, high(cur, cur_value)));VanEmdeBoasTreeNode* temp = cur->cluster[high(cur, cur_value)];cur_value = low(cur, cur_value);cur = temp;}}unsigned long long high = 0;bool first_cycle = true;while (true){if (cur->summary == nullptr)   //在叶节点删除{if (*cur->min == *cur->max){cur->min = nullptr;cur->max = nullptr;}else{if (cur_value == *cur->min)*cur->min = *cur->max;else*cur->max = *cur->min;}first_cycle = false;}else if (first_cycle)   //在只含有单一值的分支节点删除{cur->min = nullptr;cur->max = nullptr;first_cycle = false;}else{cur_value = index(cur, cur_value, high);if (cur_value == *cur->min)  //回溯到最小值被其后继替换的最后一个节点{if (cur_value == *cur->max || cur->cluster[high]->min == nullptr)removeValue(cur->summary, high);return true;  //更新该节点的summary后当前节点最大值和删除前相同,保持不变,并且当前节点对应vEB树非空,故无需向根节点调整,直接返回}if (cur_value != *cur->max)  {                         //这种情况说明从当前节点cluster数组high元素对应子树删除cur_value后,当前节点的原最大值没有被删除且现在的最大值就是原最大值,所以无需更新最大值,当然high元素对应子树被删除值后可能为空,所以需要在summary中递归删除           if (cur->cluster[high]->min == nullptr)removeValue(cur->summary, high); return true;                            //上述操作结束后注意到当前节点删除cur_value后不为空,故直接返回,无需向根节点调整}if (cur->cluster[high]->max != nullptr)            //回溯到此时的分支节点之前的搜索过程中一定没有用某节点的最小值的后继替换最小值                             *cur->max = index(cur, *cur->cluster[high]->max, high); //此外,一定从搜索结束时找到的叶节点或只含有单一值的分支节点中实际删除给定值后回溯到了当前分支节点,判断条件cur_value == *cur->max通过后一定else                                                        //从当前节点的cluster数组的high元素对应的vEB树中删除了该vEB树的最大值cur_value,且high元素之后的元素对应的vEB子树为空,这样必须用    {          shared_ptr<unsigned long long> temp = findPrecessor(cur->summary, high);    //当前节点的被删除的最大值的前驱更新当前节点最大值if (temp != nullptr)*cur->max = index(cur, *cur->cluster[*temp]->max, *temp); else*cur->max = *cur->min; removeValue(cur->summary, high);   }}if (work_stack.empty() == true)return true; cur = work_stack.top().cur;high = work_stack.top().high;work_stack.pop();}
}shared_ptr<unsigned long long> VanEmdeBoasTree::findSuccessor(VanEmdeBoasTreeNode* root, unsigned long long x)  //在以root为根的vEB树中寻找x的后继,失败返回nullptr,否则返回后继值
{stack<StackNode> work_stack;VanEmdeBoasTreeNode* cur = root;unsigned long long cur_value = x;while (true){if (cur->min == nullptr || cur_value >= *cur->max){if (work_stack.empty())return nullptr;cur = work_stack.top().cur;shared_ptr<unsigned long long> temp = findSuccessor(cur->summary, work_stack.top().high);cur_value = index(cur, *cur->cluster[*temp]->min, *temp);work_stack.pop();}else{if (cur->summary == nullptr){cur_value = *cur->max;}else if (cur_value < *cur->min){cur_value = *cur->min;}else if (cur_value == *cur->min){unsigned long long h_min = *cur->summary->min;cur_value = index(cur, *cur->cluster[h_min]->min, h_min);}else{work_stack.push(StackNode(cur, high(cur, cur_value)));VanEmdeBoasTreeNode* temp = cur->cluster[high(cur, cur_value)];cur_value = low(cur, cur_value);cur = temp;continue;}}break;//令查找到x的叶节点或x等于其最小值的分支节点为循环开始时的当前节点,如果在当前节点能够找到x的后继,则逐级向上返回到根节点,并在根结单处最终还原出x的后继//如果当前节点无法找到x的后继,则回溯至父节点,在父节点的summary中查找当前节点对应vEB树在父节点cluster中的对应下标的后继,如果找到该后继在父节点cluster中对应子树的最小值即}                  //为x后继,然后逐级向上返回,在根节点还原后继,否则回溯至祖先节点,继续利用祖先节点的summary查找x后继,处理过程和上述相同,如果最终在根节点处仍未发现x后继,则查找失败,返回nullptrunsigned long long high;while (!work_stack.empty()){cur = work_stack.top().cur;high = work_stack.top().high;work_stack.pop();cur_value = index(cur, cur_value, high);}return make_shared<unsigned long long>(cur_value);
}shared_ptr<unsigned long long> VanEmdeBoasTree::findPrecessor(VanEmdeBoasTreeNode* root, unsigned long long x) //在以root为根的vEB树中寻找x的前驱,失败返回nullptr,否则返回前驱值,过程和查找后继对称
{stack<StackNode> work_stack;VanEmdeBoasTreeNode* cur = root;unsigned long long cur_value = x;while (true){if (cur->min == nullptr || cur_value <= *cur->min){if (work_stack.empty())return nullptr;cur = work_stack.top().cur;shared_ptr<unsigned long long> temp = findPrecessor(cur->summary, work_stack.top().high);if (temp == nullptr){cur_value = *cur->min;}else{cur_value = index(cur, *cur->cluster[*temp]->max, *temp);}work_stack.pop();}else{if (cur->summary == nullptr){cur_value = *cur->min;}else if (cur_value > * cur->max){cur_value = *cur->max;}else{work_stack.push(StackNode(cur, high(cur, cur_value)));VanEmdeBoasTreeNode* temp = cur->cluster[high(cur, cur_value)];cur_value = low(cur, cur_value);cur = temp;continue;}}break;}unsigned long long high;while (!work_stack.empty()){cur = work_stack.top().cur;high = work_stack.top().high;work_stack.pop();cur_value = index(cur, cur_value, high);}return make_shared<unsigned long long>(cur_value);
}VanEmdeBoasTree::~VanEmdeBoasTree()
{stack<VanEmdeBoasTreeNode*> work_stack;   //深度优先销毁vEB树bool trace_back_flag = true;work_stack.push(root);while (work_stack.empty() == false){if (trace_back_flag){if (work_stack.top()->global_size > 1){work_stack.push(work_stack.top()->summary);}else{delete work_stack.top();work_stack.pop();trace_back_flag = false;}}else{if (work_stack.top()->cluster.empty() == false){VanEmdeBoasTreeNode* temp = work_stack.top();work_stack.push(work_stack.top()->cluster.back());temp->cluster.pop_back();trace_back_flag = true;}else{delete work_stack.top();work_stack.pop();}}}
}VanEmdeBoasTree::VanEmdeBoasTree(StyleOfCreatTree how_building_tree, unsigned int g)
{if (g <= 0 || g > 64){cout << "ERROR:全域大小超出允许范围" << endl;exit(-1);}style_of_build_tree = how_building_tree;root = new VanEmdeBoasTreeNode(g, VanEmdeBoasTreeNode::NodeType::CLUSTER);   //BFS方式构建vEB树if (style_of_build_tree == StyleOfCreatTree::BFS){deque<VanEmdeBoasTreeNode*> work_queue;work_queue.push_back(root);while (work_queue.empty() == false){VanEmdeBoasTreeNode* cur = work_queue.front();work_queue.pop_front();if (cur->global_size > 1){unsigned int k = cur->global_size >> 1;unsigned long long global = 0;if ((cur->global_size & 1) == 0){cur->summary = new VanEmdeBoasTreeNode(k, VanEmdeBoasTreeNode::NodeType::SUMMARY);global = 1U << k;}else{cur->summary = new VanEmdeBoasTreeNode(k + 1, VanEmdeBoasTreeNode::NodeType::SUMMARY);global = 1U << (k + 1);}work_queue.push_back(cur->summary);for (size_t i = 1; i <= global; ++i){cur->cluster.push_back(new VanEmdeBoasTreeNode(k, VanEmdeBoasTreeNode::NodeType::CLUSTER));work_queue.push_back(cur->cluster.back());}}}}else{struct StackNode{VanEmdeBoasTreeNode* cur;unsigned int down_sqrt;unsigned long long cluster_size;StackNode(VanEmdeBoasTreeNode* c) :cur(c) {}};stack<StackNode> work_stack;bool trace_back_flag = true;work_stack.push(StackNode(root));while (work_stack.empty() == false)      //DFS方式构建vEB树{if (trace_back_flag){if (work_stack.top().cur->global_size > 1){unsigned int k = work_stack.top().cur->global_size >> 1;size_t global = 0;if ((work_stack.top().cur->global_size & 1) == 0){work_stack.top().cur->summary = new VanEmdeBoasTreeNode(k, VanEmdeBoasTreeNode::NodeType::SUMMARY);work_stack.top().cluster_size = 1U << k;}else{work_stack.top().cur->summary = new VanEmdeBoasTreeNode(k + 1, VanEmdeBoasTreeNode::NodeType::SUMMARY);work_stack.top().cluster_size = 1U << (k + 1);}work_stack.top().down_sqrt = k;work_stack.push(StackNode(work_stack.top().cur->summary));}else{work_stack.pop();trace_back_flag = false;}}else{if (work_stack.top().cur->cluster.size() < work_stack.top().cluster_size){work_stack.top().cur->cluster.push_back(new VanEmdeBoasTreeNode(work_stack.top().down_sqrt, VanEmdeBoasTreeNode::NodeType::CLUSTER));work_stack.push(work_stack.top().cur->cluster.back());trace_back_flag = true;}else{work_stack.pop();}}}}
}int main()
{unsigned int global = 4;VanEmdeBoasTree obj(VanEmdeBoasTree::StyleOfCreatTree::DFS, global);vector<unsigned long long> input;unsigned long long j = 1ULL << global;for (unsigned long long i = 1; i <= j; ++i){input.push_back(i - 1);}shuffle(input.begin(), input.end(), default_random_engine(time(nullptr)));for (const unsigned long long& i : input){cout << "插入" << i << endl;if (obj.insert(i)){cout << "插入成功" << endl;obj.printValueInTreeFromSmallToLarge();obj.printValueInTreeFromLargeToSmall();}else{cout << "插入失败" << endl;}}obj.printValueInTreeFromLargeToSmall();obj.printValueInTreeFromSmallToLarge();for (const unsigned long long& i : input){cout << "删除" << i << endl;if (obj.remove(i)){cout << "删除成功" << endl;obj.printValueInTreeFromSmallToLarge();obj.printValueInTreeFromLargeToSmall();}else{cout << "删除失败" << endl;}}if (obj.isEmpty()){cout << "树空" << endl;}return 0;
}

van Emde Boas树实现相关推荐

  1. BZOJ 3685: 普通van Emde Boas树( 线段树 )

    建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ---------------------------------------- ...

  2. 算法导论读书笔记(20)van Emde Boas树

    第五部分 高级数据结构 第20章 van Emde Boas树 van Emde Boas树支持优先队列操作以及一些其他操作,每个操作最坏情况运行时间为O(lglgn).而这种数据结构限制关键字必须为 ...

  3. van Emde Boas 树 数据结构说解

    van Emde Boas 树的定义 直观上看,vEB 树保存了一个有序的集合,并支持以 O(lglgn) 的时间复杂度在 vEB 树上进行最小最大值查询.单值存在性查询.单值前驱后继查询.单值插入维 ...

  4. 算法导论-van Emde Boas树

    van Emde Boas树 van Emde Boas树中文名不知道,所以暂且叫它v树吧.v树是一种数据结构,和二叉树.红黑树类似.一种数据结构被创建出来,肯定有其特别的优点,v树的优点就是实现数据 ...

  5. 《算法导论3rd第二十章》van Emde Boas树

    前言 前面介绍的二叉堆,红黑树以及斐波那契堆,其重要的操作都要O(lgn).当特定条件下,能否够规避Ω(lglgn)下界的限制?在本章中,我们将看到:van Emde Boas树支持优先队列操作及一些 ...

  6. 【算法学习笔记】van Emde Boas树

    参考算法导论第20章 van Emde Boas树 文章目录 1. 基本方法 1.1 直接寻址 1.2 叠加的二叉树结构 `Superimposing a binary tree structure` ...

  7. 6.6 van Emde Boas树

      我将按四个步骤来逐一引入到van Emde Boas树.从位图到索引位图,再到van Emde Boas原型,最后到van Emde Boas树. 位图与索引位图   在java中有这个一个类,叫 ...

  8. 原型 van Emde Boas 树

    (对于一些简单的数据结构,我就不写在博客上了,然而这个van Emde Boas 树是真的有问题..) 首先,先介绍在本章中n与u的用法: n:集合中当前元素的个数: u:元素可能的取值范围: 同时, ...

  9. van Emde Boas树

    van Emde Boas树支持优先队列操作以及一些其他操作,每个操作最坏运行时间为O(lg lgn),这种数据结构限制关键字必须为0~n-1的整数且无重复.     目前参数n有两个不同的用法:一个 ...

  10. bzoj 3685 普通van Emde Boas树(坑)

    3685: 普通van Emde Boas树 Time Limit: 9 Sec Memory Limit: 128 MB Submit: 1758 Solved: 563 [Submit][Stat ...

最新文章

  1. APT 信息收集——shodan.io ,fofa.so、 MX 及 邮件。mx记录查询。censys.io查询子域名。...
  2. 百度AI实战营第二季:AI技术商业落地指南
  3. linux hadoop集群搭建,hadoop集群搭建
  4. 使用PowerDesigner做数据库设计(一)
  5. HTML5 高级系列:web Storage
  6. 沫沫金:收集Hibernate使用过程中的小技巧(不断更新)
  7. SpringMVC项目中,jsp文件无法显示从Controller中传递过来的ModelAndView的模型数据
  8. WriteFreely:创建博客,建立社区
  9. P2805 [NOI2009]植物大战僵尸
  10. 使用Eclipse查看反编译后的代码(Decompiler 插件)
  11. java中的interface
  12. python可视化(十种常用图)
  13. Java 集合源码详解
  14. 亚马逊运营应提升哪些自身能力
  15. IDM UEStudio 19中文版
  16. android 蓝牙传输文件,android-通过蓝牙发送文件
  17. mac本地安装PHP redis扩展
  18. Win10关闭蓝牙省电模式的两种方法
  19. 【Java】才疏学浅·小石Java问道之路
  20. eclipse建立Flex项目之Blazeds篇1(测试成功完整版)

热门文章

  1. (附源码)计算机毕业设计ssm电影院购票系统
  2. 全球30m土地覆盖产品(2010/2015)
  3. 知乎高赞 20 款网页神器
  4. uni-app之接入百度OCR识别身份证(微信小程序版本)
  5. win10 uwp 通过 Win2d 完全控制笔迹绘制逻辑
  6. 阿里云专有云重磅亮相中国信通院2022混合云技术发展论坛
  7. 计算机打开iis的配置,怎么打开iis? iis打开方法图解教程
  8. 大数据培训怎么选?16张国际公认的大数据“学历”证书
  9. Revit的顶点法线及threejs渲染圆弧面的渐变亮度
  10. 【Swift】用来测试的在线小视频url地址