BST树与AVL树

BST树与AVL树



一、二分查找

适用于有序数组

int binary_search(int arr[],int length,int target)
{
    int L=0,R=length-1;
    while(L<=R)
    {
        int mid=L+(R-L)/2;
        if(arr[mid]<target)
            L=mid+1;
        else if(arr[mid]>target)
            R=mid-1;
        else
            return mid;
    }
    return -1;
}

二、二叉搜索树(BST树)

1、简介

BST为二叉树
左子数所有节点都小于根节点,右子树所有节点大于根节点
每个节点的左右子树也是BST
可以在O(logN)时间复杂度内查找一个数是否存在

struct treeNode
{
    int data;
    treeNode* leftSon;
    treeNode* rightSon;
};

2、插入

创建新节点

treeNode* createTreeNode(int value)
{
    treeNode* node=new treeNode;
    node->data=value;
    node->leftSon=NULL;
    node->rightSon=NULL;
    return node;
}

插入新节点

treeNode* insertNode(treeNode* root,int value)
{
    if(root==NULL)  
        return createTreeNode(value);
    if(value<root->data)            
        root->leftSon=insertNode(root->leftSon,value);
    root->rightSon=insertNode(root->rightSon,value);
    return root;
}

操作隐患:若插入连续升序或降序节点,容易退化为线性表,复杂度为O(N)

3、查找

treeNode* searchNode(treeNode* root,int target)
{
    if(root==NULL||root->data==target)     
        return root;
    if(target<root->data)                   
        return searchNode(root->leftSon,target);
    return searchNode(root->rightSon,target);  
}

4、删除

获取BST中最小值

treeNode* getMinNode(treeNode* root)
{
    if(root==NULL)
        return NULL;
    while(root->leftSon)
    {
        root=root->leftSon;
    }
    return root;
}

删除节点

treeNode* deleteNode(treeNode* root,int target)
{   
    if(root==NULL)
        return root;
    if(target<root->data)
        root->leftSon=deleteNode(root->leftSon,target);
    else if(target>root->data)
        root->rightSon=deleteNode(root->rightSon,target);
    //开始执行删除操作
    else
    {
        //只有一个子节点或无子节点
        if(root->leftSon==NULL)
        {
            treeNode* temp=root->rightSon;
            delete root;
            return temp;
        }
        else if(root->rightSon==NULL)
        {
            treeNode* temp=root->leftSon;
            delete root;
            return temp;
        }
        //有两个子节点
        treeNode* temp=getMinNode(root->rightSon); //查找右子数最小值
        root->data=temp->data;
        root->rightSon=deleteNode(root->rightSon,temp->data);
    }
    return root;
}

三、平衡二叉树(AVL树)

1、简介

AVL树是一颗自平衡的二叉树
每个节点都有一个平衡因子 p = Height(leftSon) - Height(RightSon)
若每个节点的平衡因子的绝对值均<=1,该树是AVL树

struct treeNode
{
    int data;
    int height;
    treeNode* leftSon;
    treeNode* rightSon;
};

2、AVL树的调整

首先在叶节点插入数据
若插入导致不平衡,需对以插入路径上离插入节点最近的平衡因子绝对值大于1的节点为根的树进行调整

(1)LL型不平衡(需右单旋转)

在某个子树的左子树的左子树上插入新节点,导致根节点的平衡因子由1变为2
在这里插入图片描述

treeNode* rightRotate(treeNode* root)
{
    /*
        root             x
        / \             / \
       x  o2    ->     O  root
      / \                 / \
     O  o1              o1  o2
    */
    treeNode* x=root->leftSon;
    treeNode* o1=x->rightSon;
    x->rightSon=root;
    root->leftSon=o1;
    root->height=getHeight(root);
    x->height=getHeight(x);
    return x;
}

(2)RR型不平衡(需左单旋转)

在某个子树的右子树的右子树上插入新节点,导致根节点的平衡因子由-1变为-2
在这里插入图片描述

treeNode* leftRotate(treeNode* root)
{
    /*
        root             x
        / \             / \
      o1  x     ->   root  O
         / \         / \
       o2  O       o1  o2
    */
    treeNode* x=root->rightSon;
    treeNode* o2=x->leftSon;
    x->leftSon=root;
    root->rightSon=o2;
    root->height=getHeight(root);
    x->height=getHeight(x);
    return x;
}

(3)LR型不平衡(需左右双旋转)

在某个子树的左子树的右子树上插入新节点,导致根节点的平衡因子由1变为2
先调用再 leftRotate(root->leftSon) 调用 rightRotate(root)
在这里插入图片描述

treeNode* left_rightRotate(treeNode* root)
{
    /*
        root            root             y
        / \             / \             / \
       x  o2    ->     y  o2    ->     x   root
      / \             / \             / \   / \
    o1  y            x  O2          o1  O1 O2 o2
       / \          / \
     O1  O2       o1  O1
    */
    root->leftSon=leftRotate(root->leftSon);
    return rightRotate(root);
}

(4)RL型不平衡(需右左双旋转)

在某个子树的右子树的左子树上插入新节点,导致根节点的平衡因子由-1变为-2
在这里插入图片描述

treeNode* right_leftRotate(treeNode* root)
{
    /*
        root            root             y
        / \             / \             / \
      o1  x    ->     o1  y    ->   root   x
         / \             / \        / \   / \
        y  o2          O1  x      o1  O1 O2 o2
       / \                / \
     O1  O2             O2  o2
    */
    root->rightSon=rightRotate(root->rightSon);
    return leftRotate(root);
}

3、插入

Height的获取

int getHeight(treeNode* root)
{
    if(root==NULL)
        return 0;
    return 1+max(getHeight(root->leftSon),getHeight(root->rightSon));
}

创建新节点

treeNode* createTreeNode(int value)
{
    treeNode* node=new treeNode;
    node->data=value;
    node->height=0;
    node->leftSon=NULL;
    node->rightSon=NULL;
    return node;
};

获取平衡因子

int getBalanceFactor(treeNode* root)
{
    if(root==NULL)
        return 0;
    return getHeight(root->leftSon)-getHeight(root->rightSon);
}

插入新节点

treeNode* insertNode(treeNode* root,int value)
{
    if(root==NULL)
        return createTreeNode(value);
    if(value<root->data)
        root->leftSon=insertNode(root->leftSon,value);
    else if(value>root->data)
        root->rightSon=insertNode(root->rightSon,value);
    else
        return root;
    //调整平衡为AVL树
    root->height=getHeight(root);
    int bf=getBalanceFactor(root);
    //LL型
    if(bf>1&&value<root->leftSon->data)
        return rightRotate(root);
    //RR型
    if(bf<-1&&value>root->rightSon->data)
        return leftRotate(root);
    //LR型
    if(bf>1&&value>root->leftSon->data)
        return left_rightRotate(root);
    //RL型
    if(bf<-1&&value<root->rightSon->data)
        return right_leftRotate(root);
    return root;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值