C/C++Linux平衡二叉搜索树简介

avltree, 平衡二叉查找树,是一种特殊情况下的二叉查找树,它的特殊之处在于,对于每一个节点,其左子树深度和右子树深度之差的绝对值不大于1.

自从上次写完BSTree后,心里想写AVL树了,查了点资料,感觉自己之前的结构是真的low,哎,知耻而后勇,先说一下这次的avl与上次bstree的两点不同:

1)节点数据结构中新增了一个高度变量,代码如下:

struct Node{
    struct Node *left;
    struct Node *right;
    int val;
    int height;
    Node(int x):val(x), height(1), left(NULL), right(NULL){}
};

2)逻辑上,该树的根节点,多了一个父节点,该父节点没有实际意义,只是为了方便后续的所有关于该树的增删改查(别想到数据库。。。)的操作。形式如下图:
在这里插入图片描述
之后就要开启我们的插入和删除操作了,为什么没有查找?由于avl是一种bst,所以查找操作不在此赘述。

在这里插入图片描述

更多C/C++Linux视频资料请加qun:832218493或vx关注零声学院免费领取!

插入时,由于要保证平衡这一性质,所以要针对不同不平衡情况进行分别处理,其中,不平衡的情况分为左左失衡,右右失衡,左右失衡,右左失衡,下面进行分情况讨论处理,这里有一点需要说明的是,以上四种情况都要找到,发生不平衡的最低的树节点。

左左失衡:情况如图:
在这里插入图片描述
调整后的结果如下图:

在这里插入图片描述

struct Node *avltree::ll_rotate(struct Node *y){
    struct Node *x = y->left;
    y->left = x->right;
    x->right = y;
    y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
    x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
return x;}

右右失衡情况如下图:在这里插入图片描述
调整后如下图:在这里插入图片描述
代码奉上:

struct Node *avltree::rr_rotate(struct Node *y){
    struct Node *x = y->right;
    y->right = x->left;
    x->left = y;
    y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
    x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
    return x;
}

左右失衡如下图,这种情况需要先将x按照右右失衡情况处理,转换为左左失衡,然后按照左左失衡处理:在这里插入图片描述
第一步处理完后,如下图:在这里插入图片描述
之后就按照左左失衡处理就行了,代码奉上:

struct Node *avltree::lr_rotate(struct Node *y){
    struct Node *x = y->left;
    y->left = rr_rotate(x);
    return ll_rotate(y);
}

在这里插入图片描述
第一步调整后的结果如下图:在这里插入图片描述
之后就按照右右失衡处理就行了,代码奉上:

struct Node *avltree::rl_rotate(struct Node *y){
    struct Node *x = y->right;
    y->right = ll_rotate(x);
    return rr_rotate(y);
}

接下来奉上整个插入代码:

struct Node *avltree::insert(int k, struct Node *node){
    if(node == NULL) return (new struct Node(k));
    if(k < node->val) node->left=insert(k, node->left);
    else if( k > node->val) node->right=insert(k, node->right);
    else return node;
    node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
    int balance = isBalance(node);
    if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
    if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
    if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
    if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
    return node;
}
void avltree::insert(int k){
    root->left = insert(k, root->left);
}

删除的话,跟插入是非常类似的,直接上代码了~:

struct Node *avltree::delNode(int k, struct Node *node){
    if(node==NULL) return NULL;
    if(k < node->val) node->left = delNode(k, node->left);
    else if(k > node->val) node->right = delNode(k, node->right);
    else{
        if(node->left && node->right){
            struct Node *x = node->right;
            while(x->left) x = x->left;
            node->val = x->val;
            node->right = delNode(x->val, node->right);
        }else{
            struct Node *p = node;
            node = node->left?node->left:node->right;
            delete p, p = NULL;
            if(node == NULL) return NULL;
        }
    }
    node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
    int balance = isBalance(node);
    if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
    if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
    if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
    if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
    return node;
}
void avltree::delNode(int k){
    root->left = delNode(k, root->left);
}

整个类的代码如下:

#ifndef AVLTREE_H
#define AVLTREE_H
#include <iostream>
struct Node{
    struct Node *left;
    struct Node *right;
    int val;
    int height;
    Node(int x):val(x), height(1), left(NULL), right(NULL){}
};

class avltree
{
public:
    avltree();
    int isBalance(struct Node *node);
    int getHeight(struct Node *node);
    struct Node *ll_rotate(struct Node *y);
    struct Node *rr_rotate(struct Node *y);
    struct Node *lr_rotate(struct Node *y);
    struct Node *rl_rotate(struct Node *y);
    struct Node *insert(int k, struct Node *node);
    void insert(int k);
    struct Node *delNode(int k, struct Node *node);
    void delNode(int k);
    struct Node *root;
};

#endif // AVLTREE_H
avltree::avltree(){
    root = new struct Node(0);
}
int avltree::isBalance(struct Node *node){
    if(node == NULL) return 0;
    return getHeight(node->left) - getHeight(node->right);
}
int avltree::getHeight(struct Node *node){
    if(node == NULL) return 0;
    return node->height;
}
struct Node *avltree::ll_rotate(struct Node *y){
    struct Node *x = y->left;
    y->left = x->right;
    x->right = y;
    y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
    x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
    return x;
}
struct Node *avltree::rr_rotate(struct Node *y){
    struct Node *x = y->right;
    y->right = x->left;
    x->left = y;
    y->height = std::max(getHeight(y->left), getHeight(y->right)) +1;
    x->height = std::max(getHeight(x->left), getHeight(x->right)) +1;
    return x;
}
struct Node *avltree::lr_rotate(struct Node *y){
    struct Node *x = y->left;
    y->left = rr_rotate(x);
    return ll_rotate(y);
}
struct Node *avltree::rl_rotate(struct Node *y){
    struct Node *x = y->right;
    y->right = ll_rotate(x);
    return rr_rotate(y);
}
struct Node *avltree::insert(int k, struct Node *node){
    if(node == NULL) return (new struct Node(k));
    if(k < node->val) node->left=insert(k, node->left);
    else if( k > node->val) node->right=insert(k, node->right);
    else return node;
    node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
    int balance = isBalance(node);
    if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
    if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
    if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
    if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
    return node;
}
void avltree::insert(int k){
    root->left = insert(k, root->left);
}
struct Node *avltree::delNode(int k, struct Node *node){
    if(node==NULL) return NULL;
    if(k < node->val) node->left = delNode(k, node->left);
    else if(k > node->val) node->right = delNode(k, node->right);
    else{
        if(node->left && node->right){
            struct Node *x = node->right;
            while(x->left) x = x->left;
            node->val = x->val;
            node->right = delNode(x->val, node->right);
        }else{
            struct Node *p = node;
            node = node->left?node->left:node->right;
            delete p, p = NULL;
            if(node == NULL) return NULL;
        }
    }
    node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
    int balance = isBalance(node);
    if(balance > 1 && isBalance(node->left)>0) return ll_rotate(node);
    if(balance > 1 && isBalance(node->left)<0) return lr_rotate(node);
    if(balance < -1 && isBalance(node->right) > 0) return rl_rotate(node);
    if(balance < -1 && isBalance(node->right) < 0) return rr_rotate(node);
    return node;
}
void avltree::delNode(int k){
    root->left = delNode(k, root->left);
}

如果各位看官发现有问题,欢迎留言探讨~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值