平衡二叉树

合集下载

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡⼆叉树和⼆叉排序树(⼆叉搜索树)区别
平衡⼆叉树是⼀种⼆叉搜索树。

其可以保证在log2(n)的时间内找到节点,⽽普通的⼆叉搜索树在最坏情况下性能近似与链
表,所⽤时间为log(n)。

常⽤的平衡⼆叉树有AVL树和红⿊树其算法的难点在于插⼊删除节点后树的旋转
平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
在⼆叉搜索树的插⼊和删除运算中,采⽤平衡树的优点是:使树的结构较好,从⽽提⾼查找运算的速度。

缺点是:是插⼊和删除运算变得复杂化,从⽽降低了他们的运算速度。

对⼆叉搜索树删除节点⽽引起的不平衡性进⾏的操作⽐插⼊节点的情况要复杂,在此就不再论述了。

操作系统的设计也有⽤到哦
很多数据库的实现是基于更复杂的平衡⼆叉树
可以⾃⼰实现⼀个集合或者map,统计单词出现的次数
stl的map/set都在⽤
普通⼆叉搜索树最坏情况是只有左边⼀个分⽀,如1-2-3-4-5(5在最上⾯,1在左下⾓),但是平衡⼆叉树可以调整。

为1-2-3-4-5(3在最上⾯,1在左下⾓,5在右下⾓)。

平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
所以平衡⼆叉树的搜索性能⽐⼆叉搜索树(⼆叉排序树)好。

平衡二叉树构造过程

平衡二叉树构造过程

平衡二叉树构造过程
平衡二叉树的构造过程主要分为以下几个步骤:
1.定义平衡二叉树的结构:平衡二叉树的结构类似于普通二叉树,每
个节点的左子树和右子树的深度差不超过1。

2.插入节点:当往平衡二叉树中插入一个节点时,需要先通过二叉搜
索树的方式找到新节点的插入位置。

然后,通过旋转操作将树重新平衡。

旋转分为左旋和右旋两种操作。

3.左旋:当一个节点的右子树深度大于左子树深度时,需要进行左旋
操作。

左旋操作是将该节点的右子树进行旋转,使其成为该节点的父节点,该节点成为该节点的右子树的左子树。

4.右旋:当一个节点的左子树深度大于右子树深度时,需要进行右旋
操作。

右旋操作是将该节点的左子树进行旋转,使其成为该节点的父节点,该节点成为该节点的左子树的右子树。

5.删除节点:当从平衡二叉树中删除一个节点时,需要通过旋转操作
将树重新平衡,避免树退化成非平衡二叉树,导致性能下降。

6.重新计算节点深度:平衡二叉树的关键是保证每个节点的左子树和
右子树深度差不超过1,因此在进行节点插入和删除操作后,需要重新计
算每个节点的深度,并检查是否满足平衡二叉树的结构。

通过以上步骤,可以构造一个平衡二叉树。

在应用中,平衡二叉树常
用于高效的查找和排序操作。

平衡二叉树10.3.2

平衡二叉树10.3.2

11
28
96 98
25
(1) LL型调整 型调整 p A 1 2
调整方法: 调整方法: 单向右旋平衡,即将 的左孩子 单向右旋平衡,即将A的左孩子 B 向右上旋转代替 成为根结点, 向右上旋转代替A成为根结点 成为根结点, 结点向右下旋转成为B的右 将A结点向右下旋转成为 的右 结点向右下旋转成为 子树的根结点, 子树的根结点,而B的原右子树 的原右子树 则作为A结点的左子树 结点的左子树. 则作为 结点的左子树. h d e B
1 38 -1 24 88
0 -1 -2
0
11
28 1
96
0
-1 0
25
0
98
1,平衡二叉树插入结点的调整方法
若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 首先从根结点到该新插入结点的路径之逆向根结点方向找第一个失去平 衡的结点, 衡的结点,然后以该失衡结点和它相邻的刚查找过的两个结点构成调整 子树(最小不平衡子树 即调整子树是指以离插入结点最近,且平衡因子 最小不平衡子树), 子树 最小不平衡子树 ,即调整子树是指以离插入结点最近 且平衡因子 绝对值大于1的结点为根结点的子树 使之成为新的平衡子树. 的结点为根结点的子树,使之成为新的平衡子树 绝对值大于 的结点为根结点的子树 使之成为新的平衡子树. 38 24 88 -2
(2)RR型调整 型调整 p A -1 -2
调整方法: 调整方法: 单向左旋平衡:即将 的右孩子 的右孩子B向 单向左旋平衡:即将A的右孩子 向 左上旋转代替A成为根结点 成为根结点, 左上旋转代替 成为根结点,将A结 结 点向左下旋转成为B的左子树的根 点向左下旋转成为 的左子树的根 结点, 的原左子树则作为A结点 结点,而B的原左子树则作为 结点 的原左子树则作为 的右子树. 的右子树. B

详解平衡二叉树

详解平衡二叉树

一、平衡二叉树的概念平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:(1)左右子树深度之差的绝对值不超过1;(2)左右子树仍然为平衡二叉树.平衡因子BF=左子树深度-右子树深度.平衡二叉树每个结点的平衡因子只能是1,0,-1。

若其绝对值超过1,则该二叉排序树就是不平衡的。

如图所示为平衡树和非平衡树示意图:二、平衡二叉树算法思想若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。

首先要找出插入新结点后失去平衡的最小子树根结点的指针。

然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。

当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。

失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。

假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。

1)LL型平衡旋转法由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。

故需进行一次顺时针旋转操作。

即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。

而原来B的右子树则变成A的左子树。

(2)RR型平衡旋转法由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。

故需进行一次逆时针旋转操作。

即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。

而原来C的左子树则变成A的右子树。

(3)LR型平衡旋转法由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。

故需进行两次旋转操作(先逆时针,后顺时针)。

即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。

平衡二叉树高度计算公式

平衡二叉树高度计算公式

平衡二叉树高度计算公式
平衡二叉树的高度可以使用以下公式计算:
H = log2(N+1) - 1
其中,N为平衡二叉树中节点的个数,H为平衡二叉树的高度。

公式的基本思想是,对于一棵高度为H的平衡二叉树,它的节点数N最小值是2^H - 1,最大值是2^(H+1) - 1。

因此,根据节点数N 可以推导得到平衡二叉树的高度H。

需要注意的是,此公式适用于普通的平衡二叉树,例如AVL树、红黑树等,但对于某些特殊的平衡二叉树,可能无法直接使用此公式计算高度。

例如,B树、B+树等平衡树的高度计算方法是不同的。

此外,需要注意在实际编写代码时,为了避免精度问题,可以将公式转化为H = ceil(log(N+1)/log(2)) - 1,其中ceil函数表示向上取整。

平衡二叉树

平衡二叉树
2算法
编辑
红黑树
红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
伸展树
伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由Daniel Sleator和Robert Tarjan创造。它的优势在于不需要记录用于平衡树的冗余信息。在伸展树上的一般操作都基于伸展操作。
SBT
Size Balanced Tree(简称SBT)是一自平衡二叉查找树,是在计算机科学中用到的一种数据结构。它是由中国广东中山纪念中学的陈启峰发明的。陈启峰于2006年底完成论文《Size Balanced Tree》,并在2007年的全国青少年信息学奥林匹克竞赛冬令营中发表。由于SBT的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和ACM/ICPC选手们戏称为“傻B树”、“Super BT”等。相比红黑树、AVL树等自平衡二叉查找树,SBT更易于实现。据陈启峰在论文中称,SBT是“目前为止速度最快的高级二叉搜索树”。SBT能在O(log n)的时间内完成所有二叉搜索树(BST)的相关操作,而与普通二叉搜索树相比,SBT仅仅加入了简洁的核心操作Maintain。由于SBT赖以保持平衡的是size域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的select和rank操作。

平衡二叉树

平衡二叉树

构造二叉平衡(查找)树的方法是:
在插入过程中,采用平衡旋转技术。
例如:依次插入的关键字为5, 4, 2, 8, 6, 9
5 4 2
向右旋转 一次
4 2 5 8 2
4 6 5
先向右旋转 再向左旋转
8
6
向左旋转一次
4 2 5 6 8 9 4 6 8 5 9
继续插入关键字 9
2
④平衡调整 假设由于在二叉排序树上插入结点而失去平衡的最小子树 根结点的指针为a(即a是离插入结点最近,且平衡因子绝对值 超过1的祖先结点),则失去平衡后进行调整的规律可归纳为下 列4种情况: 1.单向右旋平衡处理: 由于在*a的左子树根结点的左子树上插入结点,*a的平衡 因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次 向右的顺时针旋转操作。如图9.6(a)所示。
0 C
RL
0 A AL CL CR
-1 B BR
插入结点
⑤插入算法 算法思想: 在平衡二叉排序树BBST上插入一个新的数据元素e的递归算法 可描述如下: 1.若BBST为空树,则插入一个数据元素为e的新结点作为 BBST的根结 点,树的深度增1; 2.若e的关键字和BBST的根结点的关键字相等,则不进行插入; 3.若e的关键字小于BBST的根结点的关键字,而且在BBST的 左子树中不存在和e有相同关键字的结点,则将e插入在BBST的 左子树上,并且当插入之后的左子树深度增加(+1)时,分别 就下列不同情况处理之:
p
lc
算法9.10如下:
#define #define #define
LH EH RH
+1 0 -1
//左高 //等高 //右高
Status InsertAVL (BSTree &T, ElemType e, Boolean &taller) { //若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入 //一个数据元素为e的新结点,并返回1,否则返回0。若因插入而使二 //叉排序树失去平衡,则作平衡旋转处理,布尔变量taller反映T长高 //与否。

平衡二叉树详解

平衡二叉树详解

平衡⼆叉树详解平衡⼆叉树详解简介平衡⼆叉树(Balanced Binary Tree)具有以下性质:它是⼀棵空树或它的左右两个⼦树的⾼度差的绝对值不超过1,并且左右两个⼦树都是⼀棵平衡⼆叉树。

平衡⼆叉树的常⽤实现⽅法有红⿊树、AVL、替罪⽺树、Treap、伸展树等。

其中最为经典当属AVL树,我们总计⽽⾔就是:平衡⼆叉树是⼀种⼆叉排序树,其中每⼀个结点的左⼦树和右⼦树的⾼度差⾄多等于1。

性值AVL树具有下列性质的⼆叉树(注意,空树也属于⼀种平衡⼆叉树):l 它必须是⼀颗⼆叉查找树l 它的左⼦树和右⼦树都是平衡⼆叉树,且左⼦树和右⼦树的深度之差的绝对值不超过1。

l 若将⼆叉树节点的平衡因⼦BF定义为该节点的左⼦树的深度减去它的右⼦树的深度,则平衡⼆叉树上所有节点的平衡因⼦只可能为-1,0,1.l 只要⼆叉树上有⼀个节点的平衡因⼦的绝对值⼤于1,那么这颗平衡⼆叉树就失去了平衡。

实现平衡⼆叉树不平衡的情形:把需要重新平衡的结点叫做α,由于任意两个结点最多只有两个⼉⼦,因此⾼度不平衡时,α结点的两颗⼦树的⾼度相差2.容易看出,这种不平衡可能出现在下⾯4中情况中:1.对α的左⼉⼦的左⼦树进⾏⼀次插⼊2.对α的左⼉⼦的右⼦树进⾏⼀次插⼊3.对α的右⼉⼦的左⼦树进⾏⼀次插⼊4.对α的右⼉⼦的右⼦树进⾏⼀次插⼊(1)LR型(2)LL型(3)RR型(4)RL型完整代码#include<stdio.h>#include<stdlib.h>//结点设计typedef struct Node {int key;struct Node *left;struct Node *right;int height;} BTNode;int height(struct Node *N) {if (N == NULL)return0;return N->height;}int max(int a, int b) {return (a > b) ? a : b;}BTNode* newNode(int key) {struct Node* node = (BTNode*)malloc(sizeof(struct Node));node->key = key;node->left = NULL;node->right = NULL;node->height = 1;return(node);}//ll型调整BTNode* ll_rotate(BTNode* y) {BTNode *x = y->left;y->left = x->right;x->right = y;y->height = max(height(y->left), height(y->right)) + 1;x->height = max(height(x->left), height(x->right)) + 1;return x;}//rr型调整BTNode* rr_rotate(BTNode* y) {BTNode *x = y->right;y->right = x->left;x->left = y;y->height = max(height(y->left), height(y->right)) + 1;x->height = max(height(x->left), height(x->right)) + 1;return x;}//判断平衡int getBalance(BTNode* N) {if (N == NULL)return0;return height(N->left) - height(N->right);}//插⼊结点&数据BTNode* insert(BTNode* node, int key) {if (node == NULL)return newNode(key);if (key < node->key)node->left = insert(node->left, key);else if (key > node->key)node->right = insert(node->right, key);elsereturn node;node->height = 1 + max(height(node->left), height(node->right)); int balance = getBalance(node);if (balance > 1 && key < node->left->key) //LL型return ll_rotate(node);if (balance < -1 && key > node->right->key) //RR型return rr_rotate(node);if (balance > 1 && key > node->left->key) { //LR型node->left = rr_rotate(node->left);return ll_rotate(node);}if (balance < -1 && key < node->right->key) { //RL型node->right = ll_rotate(node->right);return rr_rotate(node);return node;}//遍历void preOrder(struct Node *root) { if (root != NULL) {printf("%d ", root->key);preOrder(root->left);preOrder(root->right);}}int main() {BTNode *root = NULL;root = insert(root, 2);root = insert(root, 1);root = insert(root, 0);root = insert(root, 3);root = insert(root, 4);root = insert(root, 4);root = insert(root, 5);root = insert(root, 6);root = insert(root, 9);root = insert(root, 8);root = insert(root, 7);printf("前序遍历:");preOrder(root);return0;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#define EH 0 //等高
#define RH -1 //右高
//平衡二叉树的类型
struct AVLNode
{
int data;
int bf; //bf结点的平衡因子,只能够取0,-1,1,为左子树的深度减去右子树的深度
struct AVLNode *lchild,*rchild; //左、右孩子指针
{
AVLNode *rc,*rd;
rc=T->rchild;
switch(rc->bf)
{
case RH:
T->bf=rc->bf=EH;
L_Rotate(T);
break;
case LH:
rd=rc->lchild;
switch(rd->bf)
{
case RH:
T->bf=LH;
rc->bf=EH;
};
2.右旋操作:
void R_Rotate(AVLNode *&p)//LL型算法
{
AVLNode *lc=p->lchild; // lc指向p的左子树根结点
p->lchild=lc->rchild; // lc的右子树挂接为p(之前跟节点)的左子树
lc->rchild=p;
p=lc; // p指向新的根结点
插入和删除:
插入删除是互为镜像的操作。我们可以采用前面对二叉排序树的删除操作来进行。然后,在删除掉结点后,再对平衡树进行平衡化处理。删除之所以删除操作需要的平衡化可能比插入时次数多,就是因为平衡化不会增加子树的高度,但是可能会减少子树的高度,在有有可能使树增高的插入操作中,一次平衡化能抵消掉增高;在有可能使树减低的删除操作中,平衡化可能会带来祖先节点的不平衡。AVL树体现了一种平衡的美感,两种旋转是互为镜像的,插入删除是互为镜像的操作,没理由会有那么大的差别。实际上,平衡化可以统一的这样来操作:
5.查找比较关键字序列:设含有n个节点的平衡二叉树,1.求出其最大高度,和叶子节点最小层数,则比较次数最大为最大高度值其一定能找到该节点(存在),所以序列个数一定小于最大高度大于或等于叶子节点最小层数2.符合二叉排序树排序,用此排除一些选项
五、相关代码实现
1.基本结构体及变量
#define LH +1 //左高
{
if(!T) //此时为初始情况或已找到适当位置插入新数据
{
T=(AVLNode *)malloc(sizeof(AVLNode));
T->data=data;
T->lchild=T->rchild=NULL;
T->bf=EH;
*taller=1;
}
else {
if(data == T->data)
T->bf=lc->bf=EH;
R_Rotate(T);
break;
case RH: // -1新结点插入在*T的左孩子的右子树上,要作双旋处理
rd=lc->rchild; // rd指向*T的左孩子的右子树根
switch(rd->bf)
{ //根据旋转后的效果去修改T及其左孩子的平衡因子以下右旋转类似
(2)左右子树仍然为平衡二叉树.
平衡因子:平衡因子bf=左子树深度-右子树深度,
每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。增加一个元素后,平衡二叉树有可能变成不平衡了,所以需要旋转平衡调整。
平衡二叉树算法思想:
若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况:(可以断定插入一个->bf=rc->bf=EH;
break;
case LH:
T->bf=EH;
rc->bf=RH;
}
rd->bf=EH;
R_Rotate(T->rchild);
L_Rotate(T);
}
}
6.插入操作:
int InsertAVL(AVLNode *&T,int data,int *taller)
4.对树进行左平衡操作:
void LeftBalance(AVLNode *&T)
{
AVLNode *lc,*rd;
lc=T->lchild; // lc指向T的左子树根结点
switch(lc->bf)//1为左高、0等高、-1为右高
{
case LH: // 1新结点插入在*T的左孩子的左子树上,要作单右旋处理
(2)删除节点时if (current->bf) break;这时,以current为根的子树的高度和删除前的高度相同
4、当前节点移动到父节点,转1。
p = &(current->data); current = current->parent;
习题分析:
1.含有n个节点的平衡二叉树的最大高度为O(log2n)
(1)LL型平衡旋转法
由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。
(2)RR型平衡旋转法
由于在A的右孩子C的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。
case LH:
T->bf=RH;
lc->bf=EH;
break;
case EH:
T->bf=lc->bf=EH;
break;
case RH:
T->bf=EH;
lc->bf=LH;
}
rd->bf=EH;
L_Rotate(T->lchild);
R_Rotate(T);
}
}
5.对树进行右平衡操作:
void RightBalance(AVLNode *&T)
}
3.左旋操作:
void L_Rotate(AVLNode *&p)//RR型算法
{
AVLNode *rc=p->rchild; // rc指向p的右子树根结点
p->rchild=rc->lchild; // rc的左子树挂接为p的右子树
rc->lchild=p;
p=rc; // p指向新的根结点
}
(1)插入节点时current->bf += (current->data > *p)?1:-1;
(2)删除节点时current->bf -= (current->data > *p)?1:-1;
(3)current指向插入节点或者实际删除节点的父节点,这是普通二叉搜索树的插入和删除操作带来的结果。*p初始值是插入节点或者实际删除节点的data。因为删除操作可能实际删除的不是data。
T->bf=EH;
*taller=0; //标志没长高
}
}
else {
if(!InsertAVL(T->rchild,data,taller))
return 0;
if(*taller)
switch(T->bf)
{ //插入前左子树比右子树高,插入后左右子树深度相等
case LH:
T->bf=EH; //标志没长高
*taller=0;
}
}
}
return 1;
}
二叉树:
左子树都小于根节点,右子树都大于根节点。可以动态维护这棵树(因为是树结构,可以有限步完成插入),所以是动态查找算法。时间复杂度为O(logn)在46.5%的情况下,需要把二叉树平衡化成“平衡二叉树”。
平衡二叉树:定义:平衡二叉树或为空树,或为如下性质的二叉排序树:
(1)左右子树深度之差的绝对值不超过1;
(3)LR型平衡旋转法
由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理。
如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。
平衡化靠的是旋转。参与旋转的是3个节点(其中一个可能是外部节点NULL),旋转就是把这3个节点转个位置。
注意的:左旋的时候p->right一定不为空,右旋的时候p->left一定不为空,这是显而易见的。
如果从空树开始建立,并时刻保持平衡,那么不平衡只会发生在插入删除操作上,而不平衡的标志就是出现bf == 2或者bf == -2的节点。
*taller=0;
break;
case EH: //这里标识有所长高实际上此时父节点或者祖父节点的平衡因子的绝对值已经大于1
T->bf=RH;
*taller=1;
break;
case RH: //插插入前做右子树比左子树高,插入后,右子树已经长高,排序树失去平衡
相关文档
最新文档