【算法】- 查询 -平衡二叉树

文章目录

  • 前言
  • 一、平衡二叉树思想
  • 二、如何进行平衡调整
    • 2.1如何实现左平衡(L_Balance)
  • 三、平衡二叉树
  • 总结


前言

编译语言:C++
编译器:VS2022


一、平衡二叉树思想

在上节我们讲到了二叉排序树,当我们在使用二叉排序树时,要插入的数组是一个有序数组,这时二叉排序树的效率将会下降,所以就有了平衡二叉排序树来解决二叉排序树效率下降的问题。平衡二叉树的大致思想就是将数组保持平衡状态,平衡因子在-1,0,1之间不能超过,超过则视为破坏平衡,需要进行平衡调整。

二、如何进行平衡调整

首先,我们的直到根节点的平衡因子为多少,比如跟结点为1,则这时分为三种情况插入左孩子,插入右孩子,插入时使平衡因子为0。(这里我们以左孩子的插入为例)插入左孩子时我们还要判断根节点当前平衡因子状况。

#define LH +1  //左高
#define EH 0   //等高
#define RH -1  //右高
if (e < (*T)->data)//判断e值和根节点的数据大小,小就进入左孩子插入
{if (!InsertAVL(&(*T)->lchild, e, taller))//判断是否已经插入,已经插入则返回{return FALSE;}if (*taller){switch ((*T)->bf)//根据平衡因子进行判断{case LH://插入前平衡因子为1,则插入左孩子后为2,需要平衡L_Balance(T);*taller = TRUE;//由于平衡因子超过1,增长赋值为TRUEbreak;case EH://插入前平衡因子为0,则插入左孩子后为1,不需要平衡(*T)->bf = LH;//将平衡因子赋值为1*taller = FALSE;//平衡因子没超过1,则赋值为FALSEbreak;case RH://插入前平衡因子为-1,插入左孩子后为0,不需要平衡(*T)->bf = EH;*taller = FALSE;//平衡因子没有超过1,赋值为FALSEbreak;}}
}
  1. 插入前为1,插入后为2,这时打破平衡需要进行平衡调整。
case LH://插入前平衡因子为1,则插入左孩子后为2,需要平衡L_Balance(T);*taller = TRUE;//由于平衡因子超过1,增长赋值为TRUEbreak;
  1. 插入前为0,插入后为1,不需要平衡
case EH://插入前平衡因子为0,则插入左孩子后为1,不需要平衡(*T)->bf = LH;//将平衡因子赋值为1*taller = FALSE;//平衡因子没超过1,则赋值为FALSEbreak;
  1. 插入前为-1,插入后为0,不需要调整
case RH://插入前平衡因子为-1,插入左孩子后为0,不需要平衡(*T)->bf = EH;*taller = FALSE;//平衡因子没有超过1,赋值为FALSEbreak;

2.1如何实现左平衡(L_Balance)

在实现左平衡函数,我们就得直到根节点和根的左孩子的平衡因子,根据平衡因子完成左旋和右旋来完成左平衡假设L = (*T)->lchild,用L来代表T的左孩子。这时我们要判断L的平衡因子选择合适的旋转实现平衡

//左平衡
int L_Balance(BiTree* T)
{BiTree L, Lr;L = (*T)->lchild;//将T的左孩子给Lswitch (L->bf)//根据L->bf的值判断{case LH://左高 插入到L的左孩子上,只需要进行右旋R_Rotate(T);//进行右旋L->bf = (*T)->bf = EH;//将平衡因子赋值为0break;case RH://右高,插入到L的右孩子上,需要左旋一次,右旋一次Lr = L->rchild;//将Lr的右孩子给Lrswitch (Lr->bf)//根据Lr的平衡因子判断{case LH://左高,插入到Lr的左孩子上L->bf = EH;(*T)->bf = RH;break;case EH://平衡因子等高L->bf = (*T)->bf = EH;break;case RH://右高,插入到Lr的右孩子上L->bf = LH;(*T)->bf = EH;break;}Lr->bf = EH;//将Lr的平衡因子赋值为0L_Rotate(&(*T)->lchild);//左旋R_Rotate(T);//右旋}return OK;
}

1.假设插入到L的左子树上,只需要右旋转实现平衡

case LH://左高 插入到L的左孩子上,只需要进行右旋R_Rotate(T);//进行右旋L->bf = (*T)->bf = EH;//将平衡因子赋值为0break;
  1. 假设插入到L的右子树上,需要一次左旋转和一次右旋转平衡
case RH://右高,插入到L的右孩子上,需要左旋一次,右旋一次Lr = L->rchild;//将Lr的右孩子给Lrswitch (Lr->bf)//根据Lr的平衡因子判断{case LH://左高,插入到Lr的左孩子上L->bf = EH;(*T)->bf = RH;break;case EH://平衡因子等高L->bf = (*T)->bf = EH;break;case RH://右高,插入到Lr的右孩子上L->bf = LH;(*T)->bf = EH;break;}Lr->bf = EH;//将Lr的平衡因子赋值为0L_Rotate(&(*T)->lchild);//左旋R_Rotate(T);//右旋

平衡因子的调整需要对旋转的情况了解,并知道平衡因子使如何改变,这里不说明平衡因子的变化。

三、平衡二叉树

这样就可以将根据左孩子进行调整,还有根据右孩子调整,右孩子调整和左孩子调整类似,这里就不再累述了。最后看看平衡二叉树的完整代码。

#define MAXSIZE 20 //定义查询数组的长度
#define FALSE 0 
#define TRUE 1
#define OK 1
#define ERROR 0
#define LH +1  //左高
#define EH 0   //等高
#define RH -1  //右高
#include <iostream>
#include <stdlib.h>
using namespace std;
//平衡二叉树
//平衡二叉树结构体
typedef struct BinaryTree
{int data;//存放数据int bf;//存放平衡因子struct BinaryTree* lchild, * rchild;//创建左右孩子域
}BinaryTree,*BiTree;
//进行右旋
int R_Rotate(BiTree* T)
{BiTree R = (*T)->lchild;//将T的右孩子给R(*T)->lchild = R->rchild;//R的右孩子给T的左孩子R->rchild = *T;//将T给R的右孩子*T = R;//更新结点return OK;
}
//进行左旋
int L_Rotate(BiTree* T)
{BiTree L = (*T)->rchild;//将T的右孩子给L(*T)->rchild = L->lchild;//将L的左孩子给T的右孩子L->lchild = *T;//将T给L的左孩子*T = L;//更新结点return OK;
}
//左平衡
int L_Balance(BiTree* T)
{BiTree L, Lr;L = (*T)->lchild;//将T的左孩子给Lswitch (L->bf)//根据L->bf的值判断{case LH://左高 插入到L的左孩子上,只需要进行右旋R_Rotate(T);//进行右旋L->bf = (*T)->bf = EH;//将平衡因子赋值为0break;case RH://右高,插入到L的右孩子上,需要左旋一次,右旋一次Lr = L->rchild;//将Lr的右孩子给Lrswitch (Lr->bf)//根据Lr的平衡因子判断{case LH://左高,插入到Lr的左孩子上L->bf = EH;(*T)->bf = RH;break;case EH://平衡因子等高L->bf = (*T)->bf = EH;break;case RH://右高,插入到Lr的右孩子上L->bf = LH;(*T)->bf = EH;break;}Lr->bf = EH;//将Lr的平衡因子赋值为0L_Rotate(&(*T)->lchild);//左旋R_Rotate(T);//右旋}return OK;
}
//进行右平衡
int R_Balance(BiTree* T)
{BiTree R, Rl;R = (*T)->rchild;switch (R->bf){case LH://左高,插入R的左孩子,需要一次左旋转和一次右旋转Rl = R->lchild;switch (Rl->bf){case LH://左高,插入Rl的左子树R->bf = RH;(*T)->bf = EH;break;case EH://等高R->bf = (*T)->bf = EH;break;case RH://右高,插入Rl的右子树R->bf = EH;(*T)->bf = LH;break;}Rl->bf = EH;R_Rotate(&(*T)->rchild);L_Rotate(T);break;case RH://右高,插入R的右孩子,需要一次左旋L_Rotate(T);R->bf = (*T)->bf = EH;break;}return OK;
}
//平衡二叉树的插入
int InsertAVL(BiTree* T, int e, int* taller)
{if (!*T)//判断二叉树是否为空,空则创建结点,不为空则进行判断是否为e值{*T = (BiTree)malloc(sizeof(BinaryTree));(*T)->bf = EH;//将平衡因子初始化为0(*T)->lchild = (*T)->rchild = NULL;//初始化二叉树结点的左右孩子为NULL(*T)->data = e;//将数据存储在结点*taller = TRUE;//将taller赋值为增高}else//如果判断二叉树的结点不为空,则进行以下插入操作{if (e == (*T)->data){*taller = FALSE;//将taller赋值为不增长return FALSE;}if (e < (*T)->data)//判断e值和根节点的数据大小,小就进入左孩子插入{if (!InsertAVL(&(*T)->lchild, e, taller))//判断是否已经插入,已经插入则返回{return FALSE;}if (*taller){switch ((*T)->bf)//根据平衡因子进行判断{case LH://插入前平衡因子为1,则插入左孩子后为2,需要平衡L_Balance(T);*taller = TRUE;//由于平衡因子超过1,增长赋值为TRUEbreak;case EH://插入前平衡因子为0,则插入左孩子后为1,不需要平衡(*T)->bf = LH;//将平衡因子赋值为1*taller = FALSE;//平衡因子没超过1,则赋值为FALSEbreak;case RH://插入前平衡因子为-1,插入左孩子后为0,不需要平衡(*T)->bf = EH;*taller = FALSE;//平衡因子没有超过1,赋值为FALSEbreak;}}}else//如果e>(*T)->data{if (!InsertAVL(&(*T)->rchild, e, taller))//判断是否已经插入{return FALSE;}if (*taller){switch ((*T)->bf)//判断平衡因子{case LH://插入前为1,插入右孩子后为0,不需平衡(*T)->bf = EH;*taller = FALSE;break;case EH://插入前为0,插入右孩子后为-1,不需平衡(*T)->bf = RH;*taller = FALSE;break;case RH://插入前为-1,插入后右孩子为-2,需要平衡R_Balance(T);//进行有平衡*taller = TRUE;break;}}}}return OK;
}
int showTree(BiTree T)
{if (!T)return OK;else{showTree(T->lchild);printf("%d ", T->data);showTree(T->rchild);}return OK;
}
int main()
{BiTree T;T = NULL;//初始化二叉树int i;int arr[MAXSIZE] = { 5,6,8,4,2,1,9,3,7,10,15,16,18,14,12,11,19,13,17,20 };//创建待插入平衡二叉树int taller = FALSE;//记录二叉树高度是否变化,高度增高就为TRUE,高度减小就为FALSEfor (i = 0; i < MAXSIZE; i++){InsertAVL(&T,arr[i],&taller);}showTree(T);return 0;
}

总结

平衡二叉树,解决了二叉排序树因有序数据导致效率下降的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中科星图GVE(案例)——AI实现建筑用地变化前后对比情况

目录 简介 函数 gve.Services.AI.ConstructionLandChangeExtraction(image1,image2) 代码 结果 知识星球 机器学习 简介 AI可以通过分析卫星图像、航拍影像或其他地理信息数据&#xff0c;实现建筑用地变化前后对比。以下是一种可能的实现方法&#xff1a; 数据获取&am…

【Axure安装包与汉化包附带授权证书】

一、下载Axure安装包与汉化包附带授权证书 1.下载汉化包 【快传】: 点击链接即可保存 2.解压安装包 解压下载好的压缩包&#xff0c;能看到有lang也就是汉化包&#xff0c;AxureRP-Setup-RC.exe 也就是Axure9的安装程序&#xff0c;以及汉化说明和授权码。 二、安装Axure9…

小猿口算APP脚本(协议版)

小猿口算是一款专注于数学学习的教育应用,主要面向小学阶段的学生。它提供多种数学练习和测试,包括口算、速算、应用题等。通过智能化的题目生成和实时批改功能,帮助学生提高数学计算能力。此外,它还提供详细的学习报告和分析,帮助家长和教师了解学生的学习进度和薄弱环节…

【深度学习】— 多层感知机介绍、 隐藏层、从线性到非线性、线性模型的局限性

【深度学习】— 多层感知机介绍 4.1 多层感知机4.1.1 隐藏层线性模型的局限性引入隐藏层 4.2 从线性到非线性线性组合的局限性引入非线性堆叠更多隐藏层 4.1 多层感知机 在第 3 节中&#xff0c;我们介绍了 softmax 回归&#xff0c;并实现了其从零开始的实现和基于高级 API 的…

Springboot——使用poi实现excel动态图片导入解析

文章目录 前言依赖引入导入实现方式一方式二 导出参考 前言 最近要实现一个导入导出的功能点&#xff0c;需要能将带图片的列表数据导出到excel中&#xff0c;且可以导入带图片的excel列表数据。 考虑到低代码平台的表头与数据的不确定性&#xff0c;技术框架上暂定使用Apach…

IDEA下“File is read-only”可能原因及“找不到或无法加载主类”问题的解决

1.File is read-only”可能原因 写代码时想要修改这个静态变量的值&#xff0c;把这个语句注释掉&#xff0c;发现在这个文件中File is read-only无法编辑修改&#xff0c;于是想去掉这个状态 网上查看的解释大多是在File栏目或File->File Properties下可以找到Make File W…

边缘人工智能(Edge Intelligence)

边缘人工智能&#xff08;Edge AI&#xff09;是指在边缘设备上直接运行人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;算法的技术。机器学习是一个广泛的领域&#xff0c;近年来取得了巨大的进步。它所基于的原则是&#xff0c;计算机可以通过从数据…

Django ORM - 聚合查询

Django ORM - 聚合查询 Django ORM&#xff08;对象关系映射&#xff09;是一个强大的工具&#xff0c;它允许开发人员通过Python代码而不是SQL语句来操作数据库。在Django中&#xff0c;聚合查询是一种用于对数据库中的数据进行统计和分析的功能。通过使用Django ORM的聚合查…

QD1-P8 HTML 格式化标签(font、pre、b、strong、i、u、del、s、sub、sup)

本节学习&#xff1a;HTML 格式化标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p8 ‍ 一、font 标签 用途&#xff1a;定义文本的字体大小、颜色和 face&#xff08;字体类型&#xff09;。 示例 <!DOCTYPE html> <html><head><meta cha…

ssh封装上传下载

pip install paramiko import paramikoclass SSHClient:def __init__(self, host, port, username, password):self.host = hostself.port = portself.username = usernameself.password = passwordself.ssh = Noneself.sftp = Nonedef connect(self):"""连接到…

基于Kafka2.1解读Producer原理

文章目录 前言一、Kafka Producer是什么&#xff1f;二、主要组件1.Kafka Producer1.1 partitioner1.2 keySerializer1.3 valueSerializer1.4 accumulator1.5 sender 2.Sender2.1 acks2.2 client2.3 inFlightBatches 3. Selector3.1 nioSelector3.2 channels 4. 全局总览5. 一点…

TCN-Transformer时间序列预测(多输入单预测)——基于Pytorch框架

1 数据集介绍 我们使用的数据集包含以下几个重要的属性&#xff1a; date&#xff08;日期&#xff09; open&#xff08;开盘价&#xff09; high&#xff08;最高价&#xff09; low&#xff08;最低价&#xff09; close&#xff08;收盘价&#xff09; pre_close&…

使用IOT-Tree Server制作一个边缘计算设备(Arm Linux)

最近实现了一个小项目&#xff0c;现场有多个不同厂家的设备&#xff0c;用户需要对此进行简单的整合&#xff0c;并实现一些联动控制。 我使用了IOT-Tree Server这个软件轻松实现了&#xff0c;不外乎有如下过程&#xff1a; 1&#xff09;使用Modbus协议对接现有设备&#…

无人机侦测:手提式无线电侦测设备技术详解

手提式无线电侦测设备在无人机侦测中扮演着重要角色&#xff0c;它主要通过侦测无人机与遥控器或地面站之间的无线电信号来实现对无人机的监测和定位。以下是对手提式无线电侦测设备技术的详细解析&#xff1a; 一、技术原理 手提式无线电侦测设备通过无线电侦测技术&#xf…

steam上传游戏问题汇总

问题 首先是Library Logo 必须是png图片&#xff0c;还必须带上游戏名字你的宣传图不能使用游戏内部的截图。Library_Hero必须是空白的&#xff0c;不能有任何文字。他是和Library_logo合并在一起的。这个法律其实没必要填写。然后我错误的把EULA填写在这里了也报错了 如果你在…

C++刷怪笼(7)string类

目录 1.前言 2.正文 2.1标准库中的string类 2.1.1string类 2.1.2auto和范围for 2.1.3string类的常用接口说明 2.2string类的模拟实现 2.2.1经典的string类问题 2.2.2浅拷贝 2.2.3深拷贝 ​编辑 2.2.4写时拷贝 3.小结 1.前言 前面我们对C的封装这一大特性进行了详细…

java-day5

视频和笔记链接 1.数组 概念&#xff1a; ​ 指的是一种容器&#xff0c;可以同来存储同种数据类型的多个值。 ​ 但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。 比如&#xff1a; ​ 定义了一个int类型的数组。那么boolean。double类型的数据是不能存…

题目:圆桌会议

Problem - 1214 (hdu.edu.cn) 解题思路&#xff1a; 结果的顺序就是原序列的逆序&#xff0c;例如12345就是54321为结果顺序。同时将一个顺序序列&#xff08;非环&#xff09;变成逆序需要的次数为。想要的得到最短的交换次数&#xff0c;只需要将环尽量对半分&#xff0c;然后…

【万字长文】Word2Vec计算详解(三)分层Softmax与负采样

【万字长文】Word2Vec计算详解&#xff08;三&#xff09;分层Softmax与负采样 写在前面 第三部分介绍Word2Vec模型的两种优化方案。 【万字长文】Word2Vec计算详解&#xff08;一&#xff09;CBOW模型 markdown行 9000 【万字长文】Word2Vec计算详解&#xff08;二&#xff0…

Chromium 中chrome.cookies扩展接口c++实现分析

chrome.cookies 使用 chrome.cookies API 查询和修改 Cookie&#xff0c;并在 Cookie 发生更改时收到通知。 更多参考官网定义&#xff1a;chrome.cookies | API | Chrome for Developers (google.cn) 本文以加载一个清理cookies功能扩展为例 https://github.com/Google…