一、平衡树

知识点:

(1)平衡二叉树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树AVL替罪羊树Treap伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

(2)对一棵查找树(search tree)进行查询/新增/删除 等动作, 所花的时间与树的高度h 成比例, 并不与树的容量 n 成比例。如果可以让树维持矮矮胖胖的好身材, 也就是让h维持在O(lg n)左右, 完成上述工作就很省时间。能够一直维持好身材, 不因新增删除而长歪的搜寻树, 叫做balanced search tree(平衡树)。平衡树有很多种, 其中有几类树维持平衡的方法。

(3)、红黑树红黑树的平衡是在插入和删除的过程中取得的。对一个要插入的数据项,插入程序要检查不会破坏树一定的特征。如果破坏了,程序就会进行纠正,根据需要更改树的结构。通过维持树的特征,保持了树的平衡。

红黑树有两个特征:

  ①节点都有颜色

  ② 在插入和删除过程中,要遵循保持这些颜色的不同排列的规则。

  红黑规则:

    1. 每一个节点不是红色的就是黑色的

    2. 根总是黑色的

    3. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定成立)

    4. 从根到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点。(空子节点是指非叶节点可以接子节点的位置。换句话说,就是一个有右子节点的节点可能接左子节点的位置,或是有左子节点的节点可能接右子节点的位置)

   (4)、AVL树AVL树   ,它或者是一颗空二叉树,或者是具有下列性质的二叉树:

  ① 其根的左右子树高度之差的绝对值不能超过1;

  ② 其根的左右子树都是二叉平衡树。

  AVL树查找的时间复杂度为O(logN),因为树一定是平衡的。但是由于插入或删除一个节点时需要扫描两趟树,依次向下查找插入点,依次向上平衡树,AVL树不如红黑树效率高,也不如红黑树常用。

    (5)、Treap

  Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉排序树的同时,还满足的性质(在这里我们假设节点的优先级大于该节点的孩子的优先级)。但是这里要注意的是Treap和二叉堆有一点不同,就是二叉堆必须是完全二叉树,而Treap并不一定是。

 

6)由来:平衡二叉树是基于二分法的策略提高数据的查找速度的二叉树的数据结构;

7)特点:

  ①平衡二叉树是采用二分法思维把数据按规则组装成一个树形结构的数据,用这个树形结构的数据减少无关数据的检索,大大的提升了数据检索的速度;平衡二叉树的数据结构组装过程有以下规则:

  ②非叶子节点只能允许最多两个子节点存在,每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值(这里值是基于自己的算法规则而定的,比如hash值);

  

  ③平衡树的层级结构:因为平衡二叉树查询性能和树的层级(h高度)成正比、为了保证树的结构左右两端数据大致平衡降低二叉树的查询难度一般会采用一种算法机制实现节点数据结构的平衡,实现了这种算法的有比如AVL、Treap、红黑树,使用平衡二叉树能保证数据的左右两边的节点层级相差不会大于1.,通过这样避免树形结构由于删除增加变成线性链表影响查询效率,保证数据平衡的情况下查找数据的速度近于二分法查找;

 总结平衡二叉树特点:

  ①非叶子节点最多拥有两个子节点;

  ②非叶子节值大于左边子节点、小于右边子节点;

  ③树的左右两边的层级数相差不会大于1;

  ④没有值相等重复的节点;

  二叉树的优点:

  ①二叉排序树是一种比较有用的折衷方案。  数组的搜索比较方便,可以直接用下标,但删除或者插入某些元素就比较麻烦。  链表与之相反,删除和插入元素很快,但查找很慢。二叉排序树就既有链表的好处,也有数组的好处。  在处理大批量的动态的数据是比较有用。

  ②文件系统和数据库系统一般都采用树(特别是B树)的数据结构数据,主要为排序和检索的效率。二叉树是一种最基本最典型的排序树,用于教学和研究树的特性,本身很少在实际中进行应用,因为缺点太明显了(看看教科书怎么说的)。就像冒泡排序一样,虽然因为效率问题并不实用,单不失一种教学例子的好手段。

平衡二叉树都有哪些应用

  ①二叉树支持动态的插入和查找,保证操作在O(height)时间,这就是完成了哈希表不便完成的工作,动态性。但是二叉树有可能出现worst-case,如果输入序列已经排序,则时间复杂度为O(N)
平衡二叉树/红黑树就是为了将查找的时间复杂度保证在O(logN)范围内。所以如果输入结合确定,所需要的就是查询,则可以考虑使用哈希表,如果输入集合不确定,则考虑使用平衡二叉树/红黑树,保证达到最大效率

  ②平衡二叉树主要优点集中在快速查找。
如果你知道SGI/STL的set/map底层都是用红黑树(平衡二叉树的一种)实现的,相信你会对这些树大有兴趣。

 

例题:

Luogu 3369:

 

代码实现:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int N=5e5+10;
 7 int js,t,opt,b,x,y,z,rt;
 8 int v[N],p[N],s[N],c[N][2];
 9 inline int read() {
10     int n=0,f=1;char c=getchar();
11     while (c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
12     while (c<='9'&&c>='0') {n=(n<<3)+(n<<1)+c-'0';c=getchar();}
13     return n*f;
14 }
15 inline void up_date(int x){
16     s[x]=s[c[x][0]]+s[c[x][1]]+1;
17 }
18 inline int work(int u){
19     v[++js]=u;
20     s[js]=1;
21     p[js]=rand();
22     return js;
23 }
24 inline int merge(int x,int y){
25     if(!x||!y) return x+y;
26     if(p[x]<p[y]){
27         c[x][1]=merge(c[x][1],y);
28         up_date(x);
29         return x;
30     } else {
31         c[y][0]=merge(x,c[y][0]);
32         up_date(y);
33         return y;
34     }
35 }
36 inline void IUV(int now,int k,int &x,int &y){
37     if(!now) x=y=0;
38     else {
39         if(v[now]<=k) x=now,IUV(c[now][1],k,c[now][1],y);
40         else y=now,IUV(c[now][0],k,x,c[now][0]);
41         up_date(now);
42     }
43 }
44 inline int IU(int now,int k){
45     while(true){
46         if(k<=s[c[now][0]]) now=c[now][0];
47         else if(k==s[c[now][0]]+1) return now;
48         else k-=s[c[now][0]]+1,now=c[now][1];
49     }
50 }
51 int main() {
52     t=read();
53     rt=0;
54     while(t--) {
55         opt=read(),b=read();
56         if(opt==1) {
57             IUV(rt,b,x,y);
58             rt=merge(merge(x,work(b)),y);
59         }  else if(opt==2){
60             IUV(rt,b,x,z);
61             IUV(x,b-1,x,y);
62             y=merge(c[y][0],c[y][1]);
63             rt=merge(merge(x,y),z);
64         }  else if(opt==3) {
65             IUV(rt,b-1,x,y);
66             printf("%d\n",s[x]+1);
67             rt=merge(x,y);
68         }  else if(opt==4) {
69           printf("%d\n",v[IU(rt,b)]);
70         }  else if(opt==5) {
71             IUV(rt,b-1,x,y);
72             printf("%d\n",v[IU(x,s[x])]);
73             rt=merge(x,y);
74         } else if(opt==6){
75             IUV(rt,b,x,y);
76             printf("%d\n",v[IU(y,1)]);
77             rt=merge(x,y);
78         }
79     }
80     return 0;
81 }

代码实现

Luogu 3391(文艺平衡树):

 

代码实现:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int N=1e5+10;
 7 int fa[N],c[N][2],s[N],w[N];
 8 int n,m,rt,L,R;
 9 inline int read() {
10     int n=0,f=1;char ch=getchar();
11     while (ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
12     while (ch<='9'&&ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
13     return n*f;
14 }
15 inline void push_up(int x){
16     s[x]=s[c[x][0]]+s[c[x][1]]+1;
17 }
18 inline void push_down(int x){
19     if(w[x]){
20         swap(c[x][0],c[x][1]);
21         w[c[x][0]]^=1,w[c[x][1]]^=1,w[x]=0;
22     }
23 }
24 inline void rotate(int x,int &k){
25     int y=fa[x],z=fa[y],v;
26     if(c[y][0]==x) v=1;
27     else v=0;
28     if(y==k) k=x;
29     else {
30         if(c[z][0]==y) c[z][0]=x;
31         else c[z][1]=x;
32     }
33     c[y][v^1]=c[x][v],fa[c[y][v^1]]=y;
34     c[x][v]=y,fa[y]=x,fa[x]=z;
35     push_up(x),push_up(y);
36 }
37 inline void splay(int x,int &k){
38     while(x!=k){
39         int y=fa[x],z=fa[y];
40         if(y!=k){
41             if((c[y][0]==x)^(c[z][0]==y)) rotate(x,k);
42             else rotate(y,k);
43         }
44         rotate(x,k);
45     }
46 }
47 inline void build(int l,int r,int f){
48     if(l>r) return ;
49     int mid=(l+r)>>1;
50     if(mid<f) c[f][0]=mid;
51     else c[f][1]=mid;
52     fa[mid]=f,s[mid]=1;
53     if(l==r) return ;
54     build(l,mid-1,mid),build(mid+1,r,mid);
55     push_up(mid);
56 }
57 inline int find(int x,int k){
58     push_down(x);
59     int u=s[c[x][0]];
60     if(k==u+1) return x;
61     if(k<=u) return find(c[x][0],k);
62     else return find(c[x][1],k-u-1);
63 }
64 inline void work(int l,int r){
65     int x=find(rt,l),y=find(rt,r+2);
66     splay(x,rt),splay(y,c[x][1]);
67     int z=c[y][0];
68     w[z]^=1;
69 }
70 int main(){
71     n=read(),m=read();
72     rt=(n+3)/2;
73     build(1,n+2,rt);
74     for(int i=1;i<=m;++i){
75         L=read(),R=read();
76         work(L,R);
77     }
78     for(int i=2;i<=n+1;++i) printf("%d ",find(rt,i)-1);
79     return 0;
80 }

代码实现

二、二叉查找树

知识点:

二叉查找树定义:

在二叉树的基础上,每个节点有一个权值,若每个节点满足:

  1、其左子树所有权值小于等于自身权值

  2、其右子树所有权值大于等于自身权值

二叉查找树满足:按其中序遍历输出权值,那么权值不降。

二叉查找树有一个明显的缺点:

  特殊构造的数据能使树的深度达到O(n)级别,也就是每次查询或修改的最坏时间复杂度会达到O(n)。

三、Treap

知识点:

  Treap一词来源于Tree(树)与Heap(堆)的结合。

其原理是,对于每个节点,赋予一个随机权值,在构建平衡树时,使得原权值满足二叉查找树的性质,随机权值满足堆的性质,利用随机性,限制树的深度。Treap的优点为常数小。

 

转载于:https://www.cnblogs.com/Darkpurple/p/9428212.html

cyyz: Day 6 平衡树整理相关推荐

  1. cyyz: Day 4 网络流整理

    Day 4 网络流的理论性知识(算了..我自己都看不下去,还是整理些例题以后复习用吧qaq): 一.PPT(主要内容)   二.搜自度娘 定义: ①图论中的一种理论与方法,研究网络上的一类最优化问题 ...

  2. 整理一下自己手撸的博客

    这几天可能会更新的快一点,毕竟快noip了,刷很多题已经没用了,还不如整理整理以前学过的算法 算法 字符串hash入门 震惊!Vector两行代码求逆序对,六行代码过普通平衡树 八数码难题解法大全 离 ...

  3. 2019 ICPC 南昌 K. Tree(树上启发式合并,平衡树 treap)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://nanti.jisuanke.com/t/42586 Problem 给定一 ...

  4. C++ __gnu_pbds(平板电视)超详细教程(C++内置的平衡树,字典树,hash)

    整理的算法模板合集: ACM模板 目录 一.平衡树 例题:luogu P3369 [模板]普通平衡树 1. `rb_tree_tag`版 2. `splay_tree_tag`版 功能不够?自己添加! ...

  5. c++自带的可持久化平衡树?rope大法好!(超详细解答 + 5道例题讲解,可直接替代可持久化的线段树、并查集、平衡树!)

    整理的算法模板合集: ACM模板 目录 c++自带的可持久化平衡树?rope大法好! 1. 声明 2. 支持操作 char类型的rope int类型的rope 3. 具体的细节 4. "可持 ...

  6. luogu P3391 【模板】文艺平衡树(FHQ - treap,懒惰标记)

    整理的算法模板合集: ACM模板 我们把每个查询区间使用solit分裂成[1l−1][lr][r+1n][1~l-1][l~r][r+1~n][1 l−1][l r][r+1 n]三个区间. 再把[l ...

  7. 模板 - FHQ - treap 无旋平衡树

    整理的算法模板合集: ACM模板 目录 FQH - treap 无旋平衡树 按权值分裂 按排名分裂 文艺平衡树 可持久化序列 FQH - treap 无旋平衡树 operator 1 : 插入一个数 ...

  8. 平衡树 - treap

    整理的算法模板合集: ACM模板 operator 1 : 插入一个数 operator 2 : 删除一个数 operator 3 : 通过数值找排名 operator 4 : 通过排名找数值 ope ...

  9. SQL Server 数据库的整理优化的基本过程(二)

    SQL Server 数据库的整理优化的基本过程(二) 高建刚 第一节 基本维护 第二节 索引 索引相信大家都不陌生,而且在因特网上,有了很多关于如何通过索引来优化数据库的文章,在这里,我主要是结合我 ...

  10. 都写了100+原创了,是该分类整理一下

    前言 大家好,我是bigsai,最近一看公众号,哇都100+原创了,有些老铁建议我搞个目录因为有的文章翻来翻去不太好找,我之前本来想更的基本数据结构与算法差不多再搞的,但是可能还需要一段时间,可以先总 ...

最新文章

  1. python中意外缩进是什么意思_与python中的“意外缩进”怎么办?
  2. 场景法设计测试用例atm_软件测试零基础入门:常用八大测试用例设计方法,含案例...
  3. jsoup 多个 class Selector 怎么写?
  4. boost::mpl模块实现transform_view相关的测试程序
  5. 简单的信誉算法 js处理
  6. 庐山真面-Oxite的HelloWorld
  7. scala中_*的作用
  8. visual studio 2015 搭建python开发环境,python入门到精通[三]
  9. “牛津第一,16岁上大学”,中国美女学霸被骂学术媛?学术人“光鲜亮丽”就是错?...
  10. 众咖齐聚!2018智能汽车跨界融合高峰论坛开幕在即
  11. url中能出现的字符_python爬虫,解决大众点评字符库反爬机制的经验
  12. ajax 解析数组集合,ajax怎样解析json数组并用模板引擎渲染
  13. Excel中 对「对话气泡(吹き出し)」中的文字添加删除线 等操作
  14. vector的常用总结
  15. css 选择器的应用
  16. html组合标题,如何组合标题关键词(影响标题的5个因素)
  17. 【机器学习】第一章 - 机器学习概论 - 周志华机器学习笔记
  18. ai俄罗斯方块java_俄罗斯方块 AI 算法讲解
  19. python无向加权图_NetworkX:无向加权图的近似/不精确子图同构
  20. 你还会“袖手旁观”吗?

热门文章

  1. 游戏开发之静态成员实现单列设计模式(C++基础)
  2. 二、K8s Cluster详细安装步骤
  3. Python3进制转换
  4. Debian — command not found
  5. CSS3学习案例1——超级链接类型标示图标
  6. 利用有序队列寻找最大的K个数
  7. 如何在非 React 项目中使用 Redux
  8. 《Python 学习手册4th》 第十六章 函数基础
  9. 为什么读大学时做学术比搞项目重要?
  10. 【杭电ACM】1.2.6 decimal system