bst平衡树
来源:互联网 发布:mac 命令行下载文件 编辑:程序博客网 时间:2024/06/07 20:12
之前syh大神讲的时候完全不知道什么东西
在ljt和lrj的帮助下终于弄得懂了
bst是排序二叉树
简单来说就是中序遍历的结果是由小到大排序的结果
一般建树过程从根节点开始如果没有点就直接变成新的节点
如果有点就比较大小
大数去右子树
小数去左子树
重复上述操作
一般的我们认为如果数据是足够随机的话
那么bst的深度大约为logn
但是一些奇怪的数据比如直接123456.。。。。。
会使bst变成一条链
树的深度会变得很扭曲
这时我们不妨人为的让数据随机
这就是treap
我们给每个点定义一个prior
这个值用rand来取
在这treap上
我们可以通过一些旋转使prior按堆排列
这样bst就会长得像堆一样,深度非常的平衡
然后目的明确了
我们想想操作
首先对于bst我们可以进行旋转
旋转的本质就是让自己的某个儿子成为自己的父亲(很奇怪的味道)
我们思考如果这个儿子成为了父亲,那么原来的父亲的这边的子树就没了
让儿子成为父亲,就会让儿子和父亲相连,原来儿子的一个子树也无法连接。
那么正好这个多出来的子树就连在空缺处
很好理解吧
对于建treap
我们先插入节点上面提到过,
之后每插入一个节点就对于这个点和他的父子节点比较prior
如果不符合堆的性质,
就旋转。
清除
把节点往下旋转至没有两棵子树时,
直接清除节点,让子树连接父亲。(如果无子树就忽略)
通常我们可以给bst加一个size表示子树的规模
由此结合bst的性质快速进行一些操作
例如第k大数和rank
一道模板题
codevs1164
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<map> #include<ctime>using namespace std;template <typename T>class node{ public: T data; node *left_child,*right_child; int prior;};template <typename T>class treap{ private: node<T> *root; void change_right(node<T>* &n ) { node<T>*temp=n->left_child; n->left_child=temp->right_child; temp->right_child=n; n=temp; temp=0; } void change_left(node<T>* &n){ node<T>*temp=n->right_child; n->right_child=temp->left_child; temp->left_child=n; n=temp; temp=0; } void put(node<T>* &n,T data){ if(!n){ n=new node<T>; n->data=data; n->left_child=n->right_child=0; n->prior=rand()%1000000007; return ; } if(data == n->data){ n->data=data; } else if(data<n->data){ put (n->left_child,data); if(n->left_child->prior<n->prior) change_right(n); } else{ put (n->right_child,data); if(n->right_child->prior<n->prior){ change_left(n); } } } node<T> *get(node<T>* n,T data){ if(!n) return 0; if(n->data==data) return n; else if(data<n->data) return get(n->left_child,data); else return get(n->right_child,data); } void del(node<T> * n) { if(n){ del(n->left_child); del(n->right_child); delete n; } } void erase_T(node<T>* &tree,T n){ if(!tree) return ; if(!(tree->data==n)){ if(n<tree->data) erase_T(tree->left_child); else erase-T(tree->right_child); } if(!tree->left_child&&!tree->right_child) { delete tree; tree=0; } else if(tree->left_child&&tree->right_child){ if(tree->left_child->prior<=tree->right_child->prior){ change_right(tree); erase_T(tree->right_child,n); } else{ change_left(tree); erase_T(tree->left_child,n); } }else if(tree->left_child){ change_right(tree); erase_T(tree->right_child,n); } else if(tree->right_child){ change_left(tree); erase_T(tree->left_child,n); } } void dfs_lr(node<T>* &n,void(*function)(T t)){ if(!n) return ; dfs_lr(n->left_child,function); function(n->data); dfs_lr(n->right_child,function); } public : treap() { root=0; srand(time(NULL)); } ~treap() { del(root); } void insert(T data){ put(root,data); } node<T> *find(T data){ return get(root,data); } bool empty() { return (root==0); } void clear(){ del (root); } bool count(T data){ return find(data)!=0; } void erase(T data){ erase_T(root,data); } void dfs(void(*function)(T t)){ dfs_lr(root,function); }};struct p{ int x; int times; friend bool operator<(p a,p b){ return a.x<b.x; } friend bool operator ==(p a,p b){ return a.x==b.x; }};void out(p a){ printf("%d %d\n",a.x,a.times);}int main(){ treap<p> tr; int n,temp; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&temp); p a; a.x=temp; if(!tr.find(a)){ a.times=1; tr.insert(a); } else { a.times=tr.find(a)->data.times+1; tr.insert(a); } } tr.dfs(out); return 0;}
接下来看看splay
splay和treap相似
但是没有随机的prior
但是会有独特的伸展操作
对于伸展树可以合并和分裂区间
我们开始研究非旋treap
首先他叫treap所以他依然符合treap的性质每个点有一个prior
prior依然符合堆得性质,而每个点的val依然符合一个bst的性质
其次我们来看看非旋
很多的平衡树都是需要旋转的,然后不旋转的树通常可以用于可持久化
然后主要是用merge和split两种操作来实现。
然后merge操作就是合并两颗treap a,b
那么操作很简单如果a< b swap(a,b)
然后a的右子树=merge(a的右子树,b)
然后交换一下a的左右子树来满足插入期望,看不懂这个原因记住要交换就行;
资料
seg
- bst平衡树
- [平衡树]Tree(BST) + Heap = Treap
- 平衡树学习笔记(1) BST
- 二叉查找树(BST)和平衡二叉查找树(AVL)
- 判断二叉树是否为平衡二叉树(BST)
- 算法4-10:BST平衡二叉树的删除操作
- BST 随机平衡二叉树 和 快速排序
- 有序数组转换为平衡二叉树(BST)
- 有序链表转换为平衡二叉树(BST)
- 有序链表转BST(平衡查找二叉树)
- 有序链表转二叉平衡搜索树(BST)
- 平衡二叉搜索树BST转换为双向链表
- BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树
- BST二叉排序树,AVL平衡二叉树,RBT红黑树,B-树,B+树,B*树
- 《剑指offer》之二叉搜索树(BST)与平衡二叉树(AVL树)专题
- 二叉搜索树(BST)与平衡二叉树(AVL树)专题
- BST二叉查找树、AVL平衡二叉树、RBT红黑树、B-/B+/B*树性能对比
- 【数据结构与算法】十四 二叉树 BST / 平衡二叉树AVL
- 心情
- tif文件下载 保存成图片,或图片保存
- 数组反序列化
- cocos安卓打包出现的:未指定Android目标平台
- 自定义dialogfragment实现底部弹出框效果
- bst平衡树
- Dialect class not found
- 【模板】莫队 (模板题:洛谷P2009HH的项链)
- Win7系统电脑将鼠标停留在桌面图标上不出现提示信息的原因及解决方法图文教程
- linux系统中usr/bin/ld被误删/覆盖解决方案
- RecyclerView自动加载更多框架LRecyclerView(可以实现侧滑删除)
- 剑指offer 面试题14 调整数组顺序使奇数位于偶数前面
- android 开源框架之——下拉刷新,上拉加载更多总结
- google 翻译python版本