zoukankan      html  css  js  c++  java
  • 平衡二叉树

    参考博客:

    https://blog.csdn.net/isunbin/article/details/81707606

    https://blog.csdn.net/qq_25940921/article/details/82183093

    代码有所改动

    struct node{
        int key;
        int height;    //AVL树的平衡因子
        node* left;
        node* right;
        node(int k):key(k),height(1),left(nullptr),right(nullptr){}
    };
    
    class AVLTree
    {
    public:
        AVLTree() {}
        ~AVLTree() {}
        node* L_rotate(node* y);    //左旋
        node* R_rotate(node* y);    //右旋
    
        int height(node* root);
        int getBalance(node* root);
        node* insert(node* root, int key);
        node* delNode(node* root, int key);
        node* findMinNode(node* root);
        void preOrder(node *root);
    private:
    };
    #include <iostream>                                                                            
    #include <stdio.h>
    #include <string.h>
    #include "AVLTree.h"
    using namespace std;
    
    int AVLTree::height(node *N) 
    {
        if(N==nullptr)
            return 0;
        return N->height;
    }
    
    int AVLTree::getBalance(node* N)
    {
        if(N==nullptr)
            return 0;
        return height(N->left)-height(N->right);
    }
    
    node* AVLTree::L_rotate(node* root)
    {
        node* temp = root->right;
        root->right = temp->left;
        temp->left = root;
    
        root->height = max(height(root->left), height(root->right))+1;
        temp->height = max(height(temp->left), height(root->right))+1;
    
        return temp;
    }
    //右旋
    node* AVLTree::R_rotate(node* root)
    {
        node* temp = root->left;
        root->left = temp->right;
        temp->right = root;
    
        root->height = max(height(root->left), height(root->right))+1;
        temp->height = max(height(temp->left), height(temp->right))+1;
    
        return temp;
    }
    
    node* AVLTree::insert(node* root, int key)
    {
        if(root==nullptr)
            return (new node(key));
    
        if(key<root->key)
            root->left = insert(root->left, key);
        else if(key>root->key)
            root->right = insert(root->right, key);
        else
            return root;
    
        root->height = 1+max(height(root->left), height(root->right));
    
        int balance = getBalance(root); //获取当前根节点的平衡因子
    
        if(balance>1 && key < root->left->key)    //LL型
            return R_rotate(root);
    
        if(balance<-1 && key > root->right->key)   //RR型
            return L_rotate(root);
        if(balance>1 && key > root->left->key)    //LR型
        {
            //LR型,先进行左旋再右旋
            root->left = L_rotate(root->left);
            return R_rotate(root);
        }
    
        if(balance<-1 && key < root->right->key)  //RL型
        {
            //RL型,先进行右旋再左旋
            root->right = R_rotate(root->right);
            return L_rotate(root);
        }
    
        return root;
    }
    
    
    void AVLTree::preOrder(node *root)
    {
        if(root)
        {
            printf("%d ", root->key);
            preOrder(root->left);
            preOrder(root->right);
        }
    }
    
    node* AVLTree::findMinNode(node* root)
    {
        if(root==nullptr)
            return root;
        while(root->left)
            root = root->left;
        return root;
    }
    //删除指定节点,删除之后需要对树进行调整
    node* AVLTree::delNode(node* root, int key)
    {
        if(root==nullptr)
            return root;
    
        //进入左子树进行查找
        if(key < root->key)
            root->left = delNode(root->left, key);
        //进入右子树进行查找
        else if(key > root->key)
            root->right = delNode(root->right, key);
        else{
            //如果找到了指定的节点
            if((root->left==nullptr) || (root->right==nullptr))
            {
                node* temp = root->left ? root->left : root->right;
                //如果当前需要被删除的节点没有子节点的时候可以直接将当前节点删除
                if(temp==nullptr)
                {
                    delete root;
                    root=nullptr;
                }
                //如果当前节点仅存在左右子节点中的一个,那么就只要
                //将当前节点的所有信息改变为子节点的信息就行了
                else
                {
                    *root=*temp;
                    delete temp;
                }
            }
            else
            //如果当前待删除节点存在左右两个节点,那么就找到当前节点的右子树的
            //最小的节点,将待删除的节点的key改变为找到的节点的值,最后将新的节点
            //删除即可
            {
                node* temp = findMinNode(root->right);
                root->key = temp->key;
                root->right = delNode(root->right, temp->key);
            }
        }
    
        int balance = getBalance(root);
    
        if(balance > 1 && getBalance(root->left) >= 0)    //LL型
            return R_rotate(root);
    
        if(balance > 1 && getBalance(root->right) < 0)     //LR型
        {
            //LR型,先进行左旋再右旋,注意:左旋是对root的左子树,右旋是对于root
            root->left = L_rotate(root->left);
            return R_rotate(root);
        }
        if(balance < -1 && getBalance(root->right)<=0)     //RR型 
            return L_rotate(root);
    
        if(balance < -1 && getBalance(root->left) > 0)     //RL型
        {
            //RL型,先进行右旋再左旋
            root->right = R_rotate(root->right);
            return L_rotate(root);
        }
    
        //如果上面四种条件都不满足的话,就说明以当前root为根的子树是
        //一棵平衡树,不需要对其进行调整,需要递归到上一层去查看当前
        //root的根是否是一个平衡树,如此网上递归调整整棵树就可以在删
        //除了节点之后,仍然保持树的平衡状态
        
        return root;    //返回调整好的根节点
    }
    #include <iostream>
    #include "AVLTree.h"
    
    
    int main()
    {
        AVLTree avlTree;
        node* root=nullptr;
    
        root =avlTree.insert(root, 9); 
        root =avlTree.insert(root, 5); 
        root =avlTree.insert(root, 10);
        root =avlTree.insert(root, 0); 
        root =avlTree.insert(root, 6); 
        root =avlTree.insert(root, 11);
        root =avlTree.insert(root, -1);
        root =avlTree.insert(root, 1); 
        root =avlTree.insert(root, 2); 
    
        printf("preOrder: 
    ");
        avlTree.preOrder(root);                                                                    
    
        root = avlTree.delNode(root, 10);
        printf("
    
    preOrder after delete 10
    ");
        avlTree.preOrder(root);
    
        std::cout << "Hello world" << std::endl;
        return 0;
    }

  • 相关阅读:
    使用Python来临时启动端口,用来做安全时候的扫描用
    awk工作流程
    AWK的内置变量
    类型定义VS类型别名
    定义函数只能使用本地当前包中的类型,不能使用其他包中的类型
    命名类型和未命名类型和基础类型
    类型字面值
    type switch使用
    "指针"和"引用"大对比
    预测球队比赛成绩
  • 原文地址:https://www.cnblogs.com/jiguang321/p/12072697.html
Copyright © 2011-2022 走看看