数据结构(5)-- 图解AVL树

本文详细介绍了如何使用C++实现AVL树,包括对原始数据排序后构建二叉搜索树,以及通过递归和旋转操作(如LL、RR、LR、RL)维持树的平衡。作者还给出了平衡因子的计算方法和节点插入时的旋转策略。
摘要由CSDN通过智能技术生成

在原始数据上创建AVL树


我的代码尝试:

(先对原始数据进行排序,然后再填充二叉搜索树,使用递归的方式。)

#include

#include

using namespace std;

void createTree(vector& vec, TreeNode* root, int begin, int end) {

//如果只剩一个键

if (begin == end) {

root->val = vec[begin];

return;

}

int mid_sz = (begin+end)/2;

root->val = vec[mid_sz];

if (mid_sz - 1 >= begin) {

root->left = new TreeNode(0);

createTree(vec, root->left, begin, mid_sz - 1);

}

root->right = new TreeNode(0);

createTree(vec, root->right,mid_sz + 1,end);

}

void PreOrderTraverse(TreeNode* root) {

if (NULL == root)

return;

cout << root->val;

PreOrderTraverse(root->left);

PreOrderTraverse(root->right);

}

int main() {

TreeNode* roott = new TreeNode(0);

vector vec = { 0,1,2,3,4,5,6,7};

createTree(vec,roott,0,vec.size()-1);

PreOrderTraverse(roott);

}

调整树的节点使平衡的操作:旋转


LL (右旋):在左叶的左侧插入数据

图解过程:

在这里插入图片描述

在这里插入图片描述

代码实现:

//在左叶的左侧插入数据

TreeNode* LL(TreeNode* root) {

TreeNode* x = root->left; //即将返回的节点是y的左子节点(就是那个B)

TreeNode* temp = x->right; //先把y的右子节点取出来(就是那个E)

x->right = root; //把y放进x的右子节点(把A放到B的右节点)

root->left = temp; //把前面预存的放到y的左子节点(把E放到A的右节点)

return x; //(返回那个B)

}

int main() {

TreeNode* roott = new TreeNode(0);

vector vec = { 0,1,2,3,4,5,6,7};

createTree(vec,roott,0,vec.size()-1);

roott = LL(roott);

PreOrderTraverse(roott);

}


RR(左旋):在右子叶的右侧插入数据

图解过程:

在这里插入图片描述

在这里插入图片描述

右旋其实就是上面左旋的镜像过程,所以不难,直接仿写上面左旋的过程即可:

代码实现

TreeNode* RR(TreeNode* root) {

TreeNode* x = root->right; //即将返回的节点是y的右子节点

TreeNode* temp = x->left; //先把x的左子节点取出来

x->left = root; //把y放进x的左子节点

root->right = temp; //把前面预存的放到y的右子节点

return x;

}

int main() {

TreeNode* roott = new TreeNode(0);

vector vec = { 0,1,2,3,4,5,6,7};

createTree(vec,roott,0,vec.size()-1);

roott = RR(roott);

PreOrderTraverse(roott);

}


后面的部分,就比较抽象了。


LR(左右旋):在左叶节点的右侧插入数据

在这里插入图片描述

我们将这种情况抽象出来,得到下图:

在这里插入图片描述

我们需要对节点y进行平衡的维护。步骤如下图所示(第三个图里面x和z的位置换一下。):

在这里插入图片描述

代码实现

TreeNode* LR(TreeNode* root) {

root->left = RR(root->left);

root = LL(root);

return root;

}

//简单明了啊


RL(右左旋):在右叶节点的左侧插入数据

在这里插入图片描述

我们将这种情况抽象出来,得到下图:

在这里插入图片描述

我们需要对节点y进行平衡的维护。步骤如下图所示(第三个图里面x和z的位置换一下。):

在这里插入图片描述

第二个图中y的左孩子为T1

(被水印遮住的部分为:T1,T2,T3,T4)

代码实现

TreeNode* RL(TreeNode* root) {

root->right = LL(root->right);

root = RR(root);

return root;

}

//简单明了啊


新节点的插入


在这里需要先补两个函数,虽然可能现在看不懂,但是配上调用函数的上下文就懂了。

计算平衡因子

int getBalanceFactor(TreeNode* node){

if(node==NULL){

return 0;

}

return get_depth(node->left)-getHeight(node->right);

}

int get_depth(TreeNode* node){

if(node==NULL){

return 0;

}

return node->depth;

}

getBalanceFactor函数返回值的分析:

  1. 如果刚插入的叶子节点的爷爷节点的返回值大于0

  2. 如果刚插入的叶子节点的父节点的返回值大于0:(LL)

  3. 如果刚插入的叶子节点的父节点的返回值小于0:(LR)

  4. 如果刚插入的叶子节点的爷爷节点的返回值小于0

  5. 如果刚插入的叶子节点的父节点的返回值大于0:(RL)

  6. 如果刚插入的叶子节点的父节点的返回值小于0:(RR)


完整代码(测试过)


更新有点慢了,这两天事情太多,加上要调整两地状态。

#include

#include

using namespace std;

class TreeNode {

public:

//这几个数据放做公有的,方便操作

int depth; //深度,这里计算每个结点的深度,通过深度的比较可得出是否平衡

int val;

TreeNode* left;

TreeNode* right;

TreeNode(int x) : val(x), depth(0), left(NULL), right(NULL) {}

TreeNode() : val(0), depth(0), left(NULL), right(NULL) {}

int getnode() {

return this->val;

}

TreeNode* getleft() {

return this->left;

}

TreeNode* getright() {

return this->right;

}

void setleft(TreeNode* node) {

this->left = node;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

面试难免让人焦虑不安。经历过的人都懂的。但是如果你提前预测面试官要问你的问题并想出得体的回答方式,就会容易很多。

此外,都说“面试造火箭,工作拧螺丝”,那对于准备面试的朋友,你只需懂一个字:刷!

给我刷刷刷刷,使劲儿刷刷刷刷刷!今天既是来谈面试的,那就必须得来整点面试真题,这不花了我整28天,做了份“Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法等”

image

且除了单纯的刷题,也得需准备一本【JAVA进阶核心知识手册】:JVM、JAVA集合、JAVA多线程并发、JAVA基础、Spring 原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算,用来查漏补缺最好不过。

image

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
整28天,做了份“Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法等”

[外链图片转存中…(img-5by2XlWy-1712938264914)]

且除了单纯的刷题,也得需准备一本【JAVA进阶核心知识手册】:JVM、JAVA集合、JAVA多线程并发、JAVA基础、Spring 原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB、Cassandra、设计模式、负载均衡、数据库、一致性算法、JAVA算法、数据结构、加密算法、分布式缓存、Hadoop、Spark、Storm、YARN、机器学习、云计算,用来查漏补缺最好不过。

[外链图片转存中…(img-xnGae0R3-1712938264914)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值