平衡二叉树

参考博客:

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: \n");
    avlTree.preOrder(root);                                                                    

    root = avlTree.delNode(root, 10);
    printf("\n\npreOrder after delete 10\n");
    avlTree.preOrder(root);

    std::cout << "Hello world" << std::endl;
    return 0;
}

 

posted @ 2019-12-20 13:44  寅鸷  阅读(192)  评论(0编辑  收藏  举报