美文网首页
平衡二叉树AVL的左旋和右旋

平衡二叉树AVL的左旋和右旋

作者: HardMan | 来源:发表于2021-09-16 19:34 被阅读0次

AVL树

平衡二叉树是一颗自平衡的搜索二叉树,树内任何节点的左右子树的高度差不超过1。

AVL树和非AVL树

非AVL树的几种模型

右旋

image.png

针对节点8,它的左子树的高度为3,右子树高度为1,高度差超过1。并且出错的节点1和3位于8节点的左子节点4的左边。针对这种类型的非平衡树,通过右旋便可以使其重新平衡。
具体做法: 将节点8作为节点4的右子节点,节点6作为节点8的左子节点

右旋后的结果

用一个动图来表示 右旋


右旋.gif

左旋

image.png

针对节点8,它的左子树的高度是1,右子树的高度是3,高度差超过1.并且出错的节点13和15均位于节点8的右子节点12的右边,则通过左旋便可修复。


image.png

动画演示:


左旋.gif

先左旋再右旋

image.png

针对节点8,左子树的高度是3,右子树高度是1,高度差超过1。并且出错的节点5和7均位于节点8的左节点4的右边。这种情况需要先左旋再右旋便可恢复。


先左旋后

针对节点4进行左旋,左旋后变成了需要右旋的情况,可参考上面的右旋进行旋转即可。

先右旋再左旋

image.png

类似的针对12节点先进行右旋,再整体左旋,原理类似 不再赘述

代码

treeNode头文件

//
// Created by issuser on 2021/9/16.
//

#ifndef AVLTREE_TREENODE_H
#define AVLTREE_TREENODE_H
typedef int  Type;

#include <malloc.h>
class Node {
public:
    Type key;
    Node* left;
    Node* right;
    int height;

    Node(Type key,Node* left,Node* right){
        this->key=key;
        this->left=left;
        this->right=right;
        this->height=0;

    }

    ~Node(){
        this->key=NULL;
        this->left=NULL;
        this->right=NULL;
        this->height=NULL;
    }
};


#endif //AVLTREE_TREENODE_H

AVL_teee 头文件

//
// Created by issuser on 2021/9/16.
//

#ifndef AVLTREE_AVL_TREE_H
#define AVLTREE_AVL_TREE_H

#include "TreeNode.h"

class AVL_tree {
public:
    //根节点
    Node* root;
    //插入 外部调用
    void insert(Type key);
    //插入 内部循环调用
    Node* avl_insert(Node* root,Type key);
    //右旋
    Node* right_rotaion(Node* node);
    //左旋
    Node* left_rotaion(Node* node);
    //先左旋再右旋
    Node* left_right_rotaion(Node* node);
    //先右旋再左旋
    Node* right_left_rotaion(Node* node);
    //前序遍历
    void preorder_avltree(Node* tree);

};


#endif //AVLTREE_AVL_TREE_H

//
// Created by issuser on 2021/9/16.
//

#include "AVL_tree.h"
#include "android/log.h"

#define HEIGHT(p)((p==NULL)?-1:((Node*)(p))->height)

#define MAX(m,n)( (m) > (n) ? (m) : (n) )

Node *AVL_tree::avl_insert(Node *node, Type key) {
    if(node==NULL){
        node=new Node(key,NULL,NULL);
        return node;
    }
    //需要插在node的左边
    if(node->key>key){
        node->left=avl_insert(node->left,key);
        //需要插在node的右边
    } else if(node->key<key){
        node->right=avl_insert(node->right,key);
    } else{
        //不允许插入相同的key

    }
    //左子树比右子树高,出错节点位于左子树中
    if(HEIGHT(node->left)-HEIGHT(node->right)==2){
        //出错节点位于node的左子节点的左边 是需要右旋
        if(node->left->key>key){
            //右旋
            node=right_rotaion(node);
        } else{ //出错节点位于node的左节点的右边,需要先左旋再右旋
            //先左旋再右旋
            node=left_right_rotaion(node);
        }


    } else if(HEIGHT(node->right)-HEIGHT(node->left)==2){

        if(node->right->key<key){
            //左旋
            node=left_rotaion(node);
        } else{
            node=right_left_rotaion(node);
        }
    }

    //插入节点后 重新计算当前节点的高度
    node->height=MAX(HEIGHT(node->left) ,HEIGHT(node->right))+1;

    return node;


}

void AVL_tree::insert(Type key) {
    if(this->root==NULL){
        this->root=new Node(key,NULL,NULL);
        return;
    }

    this->root= avl_insert(root,key);



}
//右旋
Node* AVL_tree::right_rotaion(Node *k2) {

    Node* k1=k2->left;
    k2->left=k1->right;
    k1->right=k2;

    //旋转后 重新计算节点的高度

    k2->height=MAX(HEIGHT(k2->left),HEIGHT(k2->right))+1;
    k1->height=MAX(HEIGHT(k1->left),k2->height)+1;

    return k1;





}

Node* AVL_tree::left_rotaion(Node *k2) {
    Node* k1=k2->right;
    k2->right=k1->left;
    k1->left=k2;

    k2->height=MAX(HEIGHT(k2->left),HEIGHT(k2->right))+1;
    k1->height=MAX(k2->height,HEIGHT(k1->right))+1;
    return k1;

}

Node* AVL_tree::left_right_rotaion(Node *k3) {

    k3->left=left_rotaion(k3->left);
    return right_rotaion(k3);


}

Node* AVL_tree::right_left_rotaion(Node *k3) {
    k3->right=right_rotaion(k3->right);
    return left_rotaion(k3);
}

void AVL_tree::preorder_avltree(Node *tree) {
    if(tree!=NULL){
        __android_log_print(ANDROID_LOG_ERROR,"TAG","前序遍历====%d",tree->key);
        preorder_avltree(tree->left);
        preorder_avltree(tree->right);
    }
}

相关文章

  • 平衡二叉树AVL的左旋和右旋

    AVL树 平衡二叉树是一颗自平衡的搜索二叉树,树内任何节点的左右子树的高度差不超过1。 非AVL树的几种模型 右旋...

  • 树结构入门教程-平衡二叉树双旋转

    我们在前面学习了平衡二叉树的左旋转和右旋转,在有些特殊的需求中,往往我们只通过左旋转或者是右旋转是无法完成对二叉排...

  • 树结构入门教程-平衡二叉树右旋转

    上节我们学习了AVL树的左旋转操作,当然有左旋转肯定会有右旋转操作,关于AVL树的其他就不多说了,本节我们就直蹦主...

  • AVLtTree

    左旋转 右旋转 双旋转 左旋右旋规律 右旋右低,左旋左低,左高右旋,右高左旋左旋动左。右旋动右。新节点代替当前根节...

  • Avl平衡树--C语言实现

    Avl 平衡树 实现记录 Avl平衡二叉树和搜索二叉树基本实现原理相同,在搜索二叉树的基础上添加树平衡的操作--单...

  • 红黑树分析笔记

    阅读本文的前提 1、知道二叉查找树的概念,插入、删除和查找操作;2、知道二叉树的左旋和右旋。3、了解二叉平衡树(A...

  • 平衡二叉树AVLTree手写实现(Java)

    定义节点: 实现左旋方法: 实现右旋方法: 实现左平衡和右平衡: 实现插入元素: 完整代码: 测试输出: 结果:5...

  • 数据结构与算法(十三)平衡二叉树之AVL树

    本文主要包括以下内容: 平衡二叉树的概念 AVL树 插入操作保持AVL树的平衡 删除操作保持AVL树的平衡 平衡二...

  • AVL树,红黑树,B树,B+树

    AVL树 概念:AVL树称为平衡二叉树,对于平衡二叉树,他的每个节点的左子树和右子树之差不能超过1,如果插入或者删...

  • 音视频开发之旅(28) 算法序列 - 平衡二叉树

    目录 平衡二叉树 左旋转、右旋转、双旋转的原理 代码实现 资料 收获 上一篇我们学习实践了二叉查找树,其结合了链表...

网友评论

      本文标题:平衡二叉树AVL的左旋和右旋

      本文链接:https://www.haomeiwen.com/subject/gbfdgltx.html