数据结构(5)-- 图解AVL树(平衡二叉搜索树)

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

代码实现

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;

}

void setright(TreeNode* node) {

this->right = node;

}

};

void preorder(TreeNode* head) {

if (head == NULL) {

return;

}

cout << head->getnode() << endl;

preorder(head->getleft());

preorder(head->getright());

}

class AVL_Tree {

public:

AVL_Tree() {

}

TreeNode* right_rotate(TreeNode* root) {

TreeNode* temp = root->left;

root->left = temp->right;

temp->right = root;

return temp;

}

TreeNode* left_rotate(TreeNode* root) {

TreeNode* temp = root->right;

root->right = temp->left;

temp->left = root;

return temp;

}

TreeNode* right_left_rotate(TreeNode* root) {

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

return left_rotate(root);

}

TreeNode* left_right_rotate(TreeNode* root) {

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

return right_rotate(root);

}

int get_depth(TreeNode* node) {

if (!node) {

return 0;

}

int maxL = 0;

int maxR = 0;

//2.计算左子树的最大深度;

if (node->left != NULL)

maxL = get_depth(node->left);

//3.计算右子树的最大深度;

if (node->right != NULL)

maxR = get_depth(node->right);

//4.当前树的最大深度=左子树的最大深度和右子树的最大深度中的较大者+1

return maxL > maxR ? maxL + 1 : maxR + 1;

}

int getbalance(TreeNode* node) {

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

}

//先假设这个二叉树足够高

TreeNode* insert_node(TreeNode* head,int val) { //插入一个节点,不管三七二十一先插到叶子节点再说

if (head != NULL) {

if (val < head->val) {

head->left = insert_node(head->left, val);

}

else {

head->left = insert_node(head->right, val);

}

}

else { //这里不放else等着失败

head = new TreeNode(val);

}

//插入之后就该旋转了

if (getbalance(head) == 2) { //如果需要旋转(左边高)

if (getbalance(head->left) == 1) { //左左,需要右右旋转

return right_rotate(head); //这里还需要向上衔接

}

else if (getbalance(head->left) == -1) { //左右,这里需要右左旋转

return right_left_rotate(head);

}

}

else if (getbalance(head) == -2) { //如果需要旋转(右边高)

if (getbalance(head->right) == -1) { //右右,需要左左旋转

return left_rotate(head); //这里还需要向上衔接

}

else if (getbalance(head->right) == -1){ //左右,这里需要右左旋转

return left_right_rotate(head);

}

}

return head;

}

TreeNode* delete_node(TreeNode* head,int val) {

if (head!=NULL) {

if (val < head->val) {

head->left = delete_node(head->left, val);

}

else if(val > head->val){

head->left = delete_node(head->right, val);

}

else {

TreeNode* temp = head->left;

while (temp && temp->right) {

temp = temp->right;

}

head->val = temp->val;

if (temp->left) { //如果最右子节点还有左子节点

//那顶多就一个节点

temp->val = temp->left->val;

//temp->left = temp->left->left;

//temp->right = temp->left->right;

temp->left->val = NULL;

delete temp->left;

}

else {

temp->val = NULL;

delete temp;

}

return NULL;

}

}

if (getbalance(head) == 2) { //如果需要旋转(左边高)

if (getbalance(head->left) == 1) { //左左,需要右右旋转

return right_rotate(head); //这里还需要向上衔接

}

else if (getbalance(head->left) == -1) { //左右,这里需要右左旋转

return right_left_rotate(head);

}

}

else if (getbalance(head) == -2) { //如果需要旋转(右边高)

if (getbalance(head->right) == -1) { //右右,需要左左旋转

return left_rotate(head); //这里还需要向上衔接

}

else if (getbalance(head->right) == -1) { //左右,这里需要右左旋转

return left_right_rotate(head);

}

}

return head;

}

};

int main() {

//TreeNode* a0 = new TreeNode(0);

TreeNode* a1 = new TreeNode(1);

//TreeNode* a2 = new TreeNode(2);

TreeNode* a3 = new TreeNode(3);

//TreeNode* a4 = new TreeNode(4);

TreeNode* a5 = new TreeNode(5);

TreeNode* a6 = new TreeNode(6);

TreeNode* a7 = new TreeNode(7);

//TreeNode* a8 = new TreeNode(8);

TreeNode* a9 = new TreeNode(9);

//TreeNode* a10 = new TreeNode(10);

a5->setleft(a3);

a5->setright(a7);

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

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

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

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

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

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

img

Java核心架构进阶知识点

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Java核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、Spring相关、分布式、微服务、RPC、网络、设计模式、MQ、Redis、MySQL、设计模式、负载均衡、算法、数据结构、kafka、ZK、集群等。而这些也全被整理浓缩到了一份pdf——《Java核心架构进阶知识点整理》,全部都是精华中的精华,本着共赢的心态,好东西自然也是要分享的

image

image

image

内容颇多,篇幅却有限,这就不在过多的介绍了,大家可根据以上截图自行脑补
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
些内容对你有帮助,可以扫码获取!!(备注Java获取)**

img

Java核心架构进阶知识点

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Java核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、Spring相关、分布式、微服务、RPC、网络、设计模式、MQ、Redis、MySQL、设计模式、负载均衡、算法、数据结构、kafka、ZK、集群等。而这些也全被整理浓缩到了一份pdf——《Java核心架构进阶知识点整理》,全部都是精华中的精华,本着共赢的心态,好东西自然也是要分享的

[外链图片转存中…(img-TnlS7ej3-1713714894933)]

[外链图片转存中…(img-KKnwqeBA-1713714894933)]

[外链图片转存中…(img-lGovFnEK-1713714894933)]

内容颇多,篇幅却有限,这就不在过多的介绍了,大家可根据以上截图自行脑补
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值