AVL平衡二叉树——常用标准函数代码

AVL平衡二叉树——常用标准函数代码

AVL树仍然是一颗二叉查找树,只是在其基础上增加了**“平衡”**的要求。

由于需要对每个节点都得到平衡因子,因此需要在树的结构中加入height变量,用来记录以当前节点为根节点的子树的高度。

结构体如下:
struct node {
    int v, height;
    node *lchild, *rchild;
};
新建结点:
node* newNode(int v) {
    node* Node = new node;
    Node->v = v;
    Node->height = 1;
    Node->lchild = Node->rchild = NULL;
    return Node;
}
获取某结点(root)的高度(height):
int getHeight(node* root) {
	if(root == NULL) return 0;
	return root->height;
}
计算某结点(root)的平衡因子:
int getBalanceFactor(node* root) {
    //左子树高度减右子树高度
    return getHeight(root->lchild) - getHeight(root->rchild);
}
更新某结点(root)的高度(height):
void updateHeight(node* root) {
	//max(左孩子的height,右孩子的height) + 1
	root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
查找操作

查找AVL树中数据域为x的结点:

//首次传入的root为根节点指针,x为欲查找的元素值
void search(node* root, int x) {
    if(root == NULL) {
        printf("查找失败\n");
        return;
    }
    if(x == root->data) {
        printf("%d查找成功\n", root->data);
    } else if (x < root->data) { //如果x比当前节点小
        search(root->lchild, x); //递归左子树查找
    } else if (x >= root->data) { //如果x比当前结点大
        search(root->rchild, x); //递归右子树查找
    }
}
平衡调整

左旋

void L(node* &root) {
	//root指向结点A,temp指向结点B
	node* temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	updateHeight(root);	//更新A结点高度
	updateHeight(temp); //更新B结点高度
	root = temp;
}

右旋

void R(node* &root) {
	//root指向结点B,temp指向结点A
	node* temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	updateHeight(root);	//更新B结点高度
	updateHeight(temp); //更新A结点高度
	root = temp;
}

AVL树插入情况汇总(BF表示平衡因子)

树型判定条件调整方法
LLBF(root) = 2, BF(root->lchild) = 1对root进行右旋
LRBF(root) = 2, BF(root->lchild) = -1先对root->lchild进行左旋,再对root进行右旋
RRBF(root) = -2, BF(root->lchild) = -1对root进行左旋
RLBF(root) = -2, BF(root->lchild) = 1先对root->rchild进行右旋,再对root进行左旋
插入操作(难点)

AVL树的插入代码是在二叉查找树的插入代码的基础上增加平衡操作,因此需要在每个insert函数之后更新当前子树的高度,并在这之后根据树型是LL型、LR型、RR型、RL型之一来进行平衡操作。

//向AVL树插入权值为v的结点
void insert(node* &root, int v) {
    if(root == NULL) {
        root = newNode(v);
        return;
    }
    if(v < root->v) { //v比根节点的权值小
        insert(root->lchild, v); //往左子树插入
        updateHeight(root); //更新树高
        if(getBalanceFactor(root) == 2) { //平衡被破坏,需要调平
            if(getBalanceFactor(root->lchild) == 1) { //LL型
                R(root);
            } else if(getBalanceFactor(root->lchild) == -1) { //LR型
                L(root->lchild);
                R(root);
            }
        }
    } else { //v比根节点的权值大
        insert(root->rchild, v); //往右子树插入
        updateHeight(root); //更新树高
        if(getBalanceFactor(root) == -2) { //平衡被破坏,需要调平
            if(getBalanceFactor(root->rchild) == -1) { //RR型
                L(root);
            } else if(getBalanceFactor(root->rchild) == 1) { //RL型
                R(root->rchild);
                L(root);
            }
        }
    }
}

AVL树的建立

有了上面的基本操作,AVL树的建立就变得非常简单了,只需要依次插入n个结点即可。

node* Create(int data[], int n) {
    node* root = NULL; //新建空的根节点
    for(int i = 0; i < n; i++) {
        insert(root, data[i])
    }
    return root; //返回根结点
}

一起加油!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值