【数据结构】二叉排序树和平衡二叉树

目录

1. 二叉搜索树(BST)

1.1 二叉搜索树的定义及特点

1.1.1 定义

1.1.2 特点

1.2 二叉排序树的构造(创建)

1.2.1 基本思想

1.2.2 算法

1.3 二叉排序树的删除

2. 平衡二叉树(AVL)

2.1 为什么要用AVL

2.2 平衡二叉树相关概念

2.2.1 定义

2.2.2 平衡因子(Balance Factor)

2.2.3 最小不平衡子树

2.3 AVL树的构造和调整过程

2.3.1 基本原则

2.3.2 插入过程中的调整原则    

2.3.3 两种旋转

2.3.4 四种情况

2.3.5 平衡二叉树的查找

3.代码实现


1. 二叉搜索树(BST)

1.1 二叉搜索树的定义及特点

1.1.1 定义

[二叉搜索树 Binary Sort TreeBST] 二叉树中,任何结点均满足条件:“ 大于其左子树上的所有结点,小于其右子树上的所有结点 (若存在的话)”。又称为 二叉查找树 Binary Search Tree ),或 二叉排序树

1.1.2 特点

1 )可以实现类似折半思想的查找,有较高的查找性能
2 中序遍历二叉排序树,可得到一个有序序列!

1.2 二叉排序树的构造(创建)

1.2.1 基本思想

        只要将数据元素链到合适的位置(满足性质)。

开始二叉树为空,然后重复在二叉树中插入元素,即:

        读入数据元素

        (1)若二叉树为空,则插入到空二叉树中,即该数据元素就是根;显然是二叉排序树。

        (2)若二叉树不是空,则与根比较,若比根大则在右子树中插入,否则在左子树中插入

1.2.2 算法

// 插入节点(BST)
PtrToTreeNode InsertBST(TreeNode *root, int data) {if(root == nullptr) {root = new TreeNode;root->data = data;root->left = root->right = nullptr;} else {if(data < root->data) {root->left = InsertBST(root->left, data);} else if(data > root->data) {root->right = InsertBST(root->right, data);}}return root;
}

1.3 二叉排序树的删除

        二叉排序树的删除操作比其他操作更为复杂,有三种情况需要考虑;

(1)要删除的是叶节点——可以直接删除,然后再修改其父节点的指针。

(2)要删除的节点只有一个孩子节点——删除需要改变其父节点的指针,指向要删除节点的孩子节点。

(3)要删除的节点有左、右两棵子树——为了保持二叉搜索树的有序性,替代被删除的元素位置可以有两种选择:一种是取其右子树中的最小元素;另一个是取其左子树中的最大元素。

2. 平衡二叉树(AVL)

2.1 为什么要用AVL

        动态查找表本身是在查找过程中动态生成,即对于给定值key,若查找表中存在其关键码等于key的元素,则查找成功返回,否则插入关键码等于key的元素。

        动态查找表可以是线性表,也可以是树(二叉排序树)。最常用的动态查找表是: 二叉排序树。

查找方法:

        若二叉排序树为空,则查找不成功,在二叉排序树中插入该元素;否则:

        ①  若给定值等于根结点的关键字,则查找成功;

        ②  若给定值小于根结点的关键字,则继续在左子树上进行查找;

        ③  若给定值大于根结点的关键字,则继续在右子树上进行查找。

特点:查找效率与构造的二叉排序树的深度有关;

        对于每一颗特定的二叉排序树,均可按照平均查找长度的定义来求它的ASL值:

ASL=\sum_{i=1}^{n} p_{i}\times c_{i}

        其中:p_{i}是查找第 i 个元素的概率,通常假设为等概率

                   c_{i}是查找第 i 个元素的比较次数,这里 c_{i}=h_{i}

        显然,由n个关键字构造所得的不同形态的各棵二叉排序树的平均查找长度的值不同,甚至可能差别很大。

例如:

        由关键字序列 [1,2,3,4,5] 构造而得的二叉排序树:

                ASL =(1+2+3+4+5)/ 5 = 3

        由关键字序列 [3,1,2,5,4] 构造而得的二叉排序树:

                 ASL =(1+2+3+2+3)/ 5 = 2.2

         所有这些二叉排序树中,最高n,最低 log_{2}n

        如何构造一棵查找效率高的二叉排序树?

2.2 平衡二叉树相关概念

2.2.1 定义

        一棵二叉排序树是平衡的,当且仅当每个结点的左右子树的高度至多相差为1 。由G.M.Adelson-Velskii 和 E.M.Landis给出的定义—— AVL树。

递归定义:

(1)空树是二叉排序树(平衡二叉树);

(2)它的左右子树都是平衡二叉树(左右子树的高度最多相差为1);

2.2.2 平衡因子(Balance Factor)

        左子树的高度-右子树的高度,即 BF=H_{left}-H_{right}

        平衡二叉树中,对任意结点:BF = 1、0、-1,即 BF的绝对值小于等于1,如果大于1,平衡二叉树就失衡,需要旋转纠正。

2.2.3 最小不平衡子树

        距离插入节点最近的,并且 BF 的绝对值大于 1 的节点为根节点的子树。

        旋转纠正只需要纠正最小不平衡子树!

2.3 AVL树的构造和调整过程

2.3.1 基本原则

        按照二叉排序树的构造方法,构造过程中判断是否为平衡二叉树(平衡因子),是,则继续构造;否则,按一定的原则(保持是二叉排序树和平衡)将其调整为平衡二叉树,然后继续。

2.3.2 插入过程中的调整原则    

        二叉排序树在插入前平衡,插入一个结点后如果失去平衡,则至少有一个结点 的平衡因子变为+2或-2。

        若平衡因子=+2,则左分支高于右分支;

        若平衡因子=-2,则右分支高于左分支;

2.3.3 两种旋转

  1. 左旋
    • 旧根节点为新根节点的左子树
    • 新根节点的左子树(如果存在)为旧根节点的右子树
  2. 右旋:
    • 旧根节点为新根节点的右子树
    • 新根节点的右子树(如果存在)为旧根节点的左子树

2.3.4 四种情况

LL型:在左分支的左子树上插入一个结点后,失去平衡,BF=2

右旋

LR型:在左分支的右上子树插入一个结点后,失去平衡,BF=2

先左旋,再右旋

RR型:在右分支的右子树上插入一个结点后,失去平衡,BF=-2

左旋

RL型:在右分支的左子树上插入一个结点后,失去平衡,BF=-2

先右旋,再左旋

2.3.5 平衡二叉树的查找

         1. 查找过程:同静态二叉排序树一样!

        2. 效率分析: 查找过程中和给定值进行比较的关键字的个数不超过平衡树的深度。 假设深度为 h 的二叉平衡树中所含结点数的最小值为 N_{h} ,则显然 N_{h}=N_{h-1}+N_{h-2}+1

                由此可以推导出:h\approx log_{2}n

                因此,在平衡树上进行查找的时间复杂度为 O(log_{2}(n))

3.代码实现

// 二叉树结点定义
typedef struct TreeNode{int data;struct TreeNode *left;struct TreeNode *right;int height;
} TreeNode, *PtrToTreeNode;// 插入节点(BST)
PtrToTreeNode InsertBST(TreeNode *root, int data) {if(root == nullptr) {root = new TreeNode;root->data = data;root->left = root->right = nullptr;} else {if(data < root->data) {root->left = InsertBST(root->left, data);} else if(data > root->data) {root->right = InsertBST(root->right, data);}}return root;
}// 计算树的高度
int Height(TreeNode *root) {if(root == nullptr) {return -1;} else {return max(Height(root->left), Height(root->right)) + 1;}
}// 获取平衡因子
int GetBalance(TreeNode *root) {return root ? Height(root->left) - Height(root->right) : 0;
}// 左旋
TreeNode *LeftRotate(TreeNode *root) {TreeNode *newRoot = root->right; // 新根节点root->right = newRoot->left; // 新根的左子树newRoot->left = root; // 新根的左子树指向原根节点root->height = max(Height(root->left), Height(root->right)) + 1;newRoot->height = max(Height(newRoot->left), Height(newRoot->right)) + 1;return newRoot;
}// 右旋
TreeNode *RightRotate(TreeNode *root) {TreeNode *newRoot = root->left; // 新根节点root->left = newRoot->right; // 新根的右子树newRoot->right = root; // 新根的右子树指向原根节点root->height = max(Height(root->left), Height(root->right)) + 1;newRoot->height = max(Height(newRoot->left), Height(newRoot->right)) + 1;return newRoot;
}// 插入节点(AVL)
TreeNode *InsertAVL(TreeNode *root, int data) {if(root == nullptr) {root = new TreeNode;root->data = data;root->left = root->right = nullptr;return root;} else {if(data < root->data) {root->left = InsertAVL(root->left, data);} else if(data > root->data) {root->right = InsertAVL(root->right, data);}}root->height = max(Height(root->left), Height(root->right)) + 1;int balance = GetBalance(root);// 左子树高度大于右子树高度if(balance > 1) {// LL型if(Height(root->left->left) > Height(root->left->right)) {root = RightRotate(root);} else { //LR型root->left = LeftRotate(root->left);root = RightRotate(root);}} else if(balance < -1) { // 右子树高度大于左子树高度// RR型if(Height(root->right->right) > Height(root->right->left)) {root = LeftRotate(root);} else { // RL型root->right = RightRotate(root->right);root = LeftRotate(root);}}return root;
}// 计算查找长度
int SearchLength(TreeNode *root, int depth) {if(root == nullptr) {return 0;} else {return depth + SearchLength(root->left, depth + 1) + SearchLength(root->right, depth + 1);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C++四种类型转换

C语言提供了四种类型转换 const_cast: 可以去除掉常量属性的类型转换 //const_cast const int a 10; double* p1 (double*)&a;//类型和原来的类型可以不一致&#xff0c;但是不安全 int* p2 const_cast<int*>(&a);//类型和原本的类型必须匹配 //<>中必…

【SPIE出版,往届稳定EI检索】2024智能视觉与数据建模国际学术会议(ICIVD 2024,12月13-15日)

2024智能视觉与数据建模国际学术会议 2024 International Conference on Intelligent Vision and Data modeling (ICIVD 2024) 重要信息 会议官网&#xff1a;www.iccaid.net 2024 International Conference on Intelligent Vision and Data modeling (ICIVD 2024)www.iccaid…

大模型的思维链提示

文章目录 思维链提示的基本形式思维链提示的优化策略关于思维链的进一步讨论思维链提示是一种高级提示策略,旨在增强大语言模型在各类复杂推理任务上的表现。常见的推理任务包括算术推理、常识推理以及符号推理等多种任务。与上下文学习方法仅使用⟨输入,输出⟩二元组来构造提…

JavaScript day01 笔记

一、引入方式 JavaScript 程序不能独立运行&#xff0c;它需要被嵌入 HTML 中&#xff0c;然后浏览器才能执行 JavaScript 代码。通过 script 标签将 JavaScript 代码引入到 HTML 中 1️⃣内部 通过 script 标签包裹 JavaScript 代码&#xff08;一般就写在</script>的…

vue,uniapp,微信小程序解决字符串中出现数字则修改数字样式,以及获取字符串中的数字

简单记录一下&#xff0c;最近遇到的一个新需求&#xff1a;后端返回的是非富文本&#xff0c;只是一串字符串&#xff0c;其中包含了文字和数字&#xff0c;前端需要将出现数字的地方将其加粗或者修改颜色等需求 设计思路&#xff1a;&#xff08;简单做个记录方便以后理解&a…

数据分析:16s差异分析DESeq2 | Corncob | MaAsLin2 | ALDEx2

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍DESeq2原理计算步骤结果Corncob原理计算步骤结果MaAsLin2原理计算步骤结果ALDEx2原理计算步骤结果加载R包数据链接数据预处理微生物数据样本信息提取物种名称过滤零值保留结果读取…

【CSS】标准怪异盒模型

概念 CSS 盒模型本质上是一个盒子&#xff0c;盒子包裹着HTML 元素&#xff0c;盒子由四个属性组成&#xff0c;从内到外分别是&#xff1a;content 内容、padding 内填充、border 边框、外边距 margin 盒模型的分类 W3C 盒子模型(标准盒模型) IE 盒子模型(怪异盒模型) 两种…

C++builder中的人工智能(18):神经网络中的SoftMax函数

在这篇文章中&#xff0c;我们将探讨SoftMax函数在神经网络中的作用&#xff0c;如何在人工神经网络&#xff08;ANN&#xff09;中使用SoftMax函数&#xff0c;以及在AI技术中SoftMax的应用场景。让我们来详细解释这些概念。 SoftMax函数是什么&#xff1f; SoftMax函数是逻辑…

机器学习(七)——集成学习(个体与集成、Boosting、Bagging、随机森林RF、结合策略、多样性增强、多样性度量、Python源码)

目录 关于1 个体与集成2 Boosting3 Bagging与随机森林4 结合策略5 多样性X 案例代码X.1 分类任务-Adaboost-SVMX.1.1 源码X.1.2 数据集&#xff08;鸢尾花数据集&#xff09;X.1.3 模型效果 X.2 分类任务-随机森林RFX.2.1 源码X.2.2 数据集&#xff08;鸢尾花数据集&#xff09…

Matlab轻松烟雾检测

小编经验分享&#xff1a;如何使用Matlab进行烟雾检测 烟雾检测是一项重要的安全技术&#xff0c;它可以帮助我们及时发现火灾风险并采取相应的措施。在这篇文章中&#xff0c;小编将和大家分享如何使用Matlab进行烟雾检测的经验。希望这些经验对大家在实际应用中能够有所帮助…

c语言其实很简单----【数组】

TOC 1.输入10个学生成绩&#xff0c;计算及格人数&#xff0c;平均成绩&#xff0c;总成绩。 #include<stdio.h> int main(){float score[10];int i ,cut;float avar0.0,sum0.0;for(i0;i<10;i)scanf("%f",&score[i]);//输入10个学生的成绩cut0;for(i0…

在 .NET 6.0 中创建用于 CRUD 操作的 Web API

快速概述&#xff1a; 在动态的技术世界中&#xff0c;创建强大的 Web API 已成为开发人员不可或缺的关键技能。这些 API 是促进不同应用程序之间顺畅通信的重要链接&#xff0c;可实现无缝数据检索和操作。本文的重点是在 .NET 6 中为 CRUD 操作创建 Web API。 为了实现这一点…

lua 编译网路核心

下载 Severity Code Description Project File Line Suppression State Details Error LNK1104 cannot open file lua53.lib mime D:\MyWork\lua\luasocket-master\luasocket-master\LINK 1 2> Creating library Release\soc…

SystemC学习(4)— 在VCS中运行SystemC

SystemC学习&#xff08;4&#xff09;— 在VCS中运行SystemC 一、前言 参考&#xff1a;VCS编译verilog&SystemC 二、仅包含SystemC的仿真 源文件使用上一篇&#xff1a;SystemC学习&#xff08;3&#xff09;— APB_SRAM的建模与测试 编写makefile如下所示&#xff…

Qt第三课 ----------布局

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

MySQL本地安装及密码重置常见错误处理

文章目录 一、MySQL下载二、配置环境变量三、MySQL初始化1.初始化MySQL数据库2.安装MySQL服务3.启动MySQL服务 四、密码重置 一、MySQL下载 官网地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.5.html#downloads 下载完成后&#xff0c;直接解压缩到D盘 二、配置…

TBB开启并行编程之旅

本文基于小彭老师TBB课程&#xff0c;并对部分晦涩知识添加了更详细的解释与示例 第0章&#xff1a;从并发到并行 停滞的摩尔定律 你醒啦&#xff1f;免费午餐结束了&#xff01; 摩尔定律具体内容我们就不再提&#xff0c;从上图可以看到晶体管的密度的确仍在指数增长&…

「QT」几何数据类 之 QPointF 浮点型点类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

青藤深度参编的终端安全国家标准正式发布

近日&#xff0c;国家市场监督管理总局、国家标准化管理委员会发布中华人民共和国国家标准公告&#xff0c;由TC260&#xff08;全国网络安全标准化技术委员会&#xff09;归口&#xff0c;公安部第三研究所牵头的GB/T 29240-2024《网络安全技术 终端计算机通用安全技术规范》&…

[极客大挑战 2019]Secret File 1

[极客大挑战 2019]Secret File 1 审题 看到题目应该是一道简单的按照要求找flag的题目 知识点 跟着题目走 解题 一&#xff0c;查看源码 找到网站进入 点开发现 【注意它说没看清吗】 二&#xff0c;使用BP抓包试试 发现新出现了/action.php 抓到后放到Repeater中响应 得…