AVL二叉搜索树的插入算法

本文介绍了AVL树的定义,它是二叉搜索树的一种,通过维护平衡因子确保插入后树的高度差不超过1。详细讲解了四种不平衡情况及其对应的旋转操作:LL形、RR形、LR形和RL形,并提供了完整的插入代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平衡AVL二叉搜索树的插入自平衡算法

AVL树

AVL 树是一种平衡二叉树,得名于其发明者的名字( Adelson-Velskii 以及 Landis)。
平衡二叉树递归定义如下:

  • 什么是二叉搜索树
    任一结点 小于 其左子树的所有结点小于 其右子树的所有结点;
    结点的左右子树,也是二叉排序树;
    在这里插入图片描述

  • 什么是AVL树
    搜索二叉树的每个结点的左、右子树高度之差的绝对值不超过1.
    同时引入平衡因子的概念,即:结点的平衡因子= 右子树高度 – 左子树高度
    在这里插入图片描述

AVL树节点定义

节点包括:

AVLTreeNodeType
val(节点值)int
bf(平衡因子)int
leftTree(左子树)AVLTreeNode*
leftTree(右子树)AVLTreeNode*

定义如下:

struct AVLTreeNode
{
	int val;					// 节点值
	int bf;						// 平衡因子
	AVLTreeNode* leftTree;		// 左子树
	AVLTreeNode* rightTree;		// 右子树
	AVLTreeNode() :val(0), bf(0), leftTree(NULL), rightTree(NULL) {}
	AVLTreeNode(int valable) :val(valable), bf(0), leftTree(NULL), rightTree(NULL) {}
	AVLTreeNode(int valable, int be, AVLTreeNode* lf, AVLTreeNode* rf) :val(valable), bf(be), leftTree(lf), rightTree(rf) {}
	AVLTreeNode* setAVLTree(vector<int> nums);			// 插入平衡算法
};

平衡方式

LL形

  • 不平衡原因:新结点插入到A的左子女的左子树中导致不平衡
    在这里插入图片描述

算法:

void rotateLL(AVLTreeNode*& root) {
	AVLTreeNode* currL = root;
	root = currL->rightTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	root->bf = currL->bf = 0;
}

图示:
在这里插入图片描述

RR形

  • 不平衡原因:新结点插入到A的右子女的右子树中导致不平衡
    在这里插入图片描述

算法示例:

void rotateRR(AVLTreeNode*& root) {
	AVLTreeNode* curr = root;
	root = curr->leftTree;
	curr->leftTree = root->rightTree;
	root->rightTree = curr;
	root->bf = curr->bf = 0;
}

图示过程:
在这里插入图片描述

LR形

  • 不平衡原因:新结点插入到A的左子女的右子树中导致不平衡
    在这里插入图片描述

算法示例:

void rotateLR(AVLTreeNode*& root) {
	AVLTreeNode* currL = root->leftTree;
	AVLTreeNode* currR = root;
	root = currL->rightTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	if (root->bf <= 0)currL->bf = 0;
	else
		currL->bf = -1;

	currR->leftTree = root->rightTree;
	root->rightTree = currR;
	if (root->bf == -1)
		currR->bf = 1;
	else
		currR->bf = 0;
	root->bf = 0;
}

图示过程:
在这里插入图片描述

RL形

  • 不平衡原因:新结点插入到A的右子女的左子树中导致不平衡

在这里插入图片描述

算法示例:

void rotateRL(AVLTreeNode*& root) {
	AVLTreeNode* currL = root;
	AVLTreeNode* currR = currL->rightTree;
	root = currR->leftTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	if (root->bf == 1)
		currL->bf = -1;
	else
		currL->bf = 0;
	currR->leftTree = root->rightTree;
	root->rightTree = currR;
	if (root->bf >= 0)
		currR->bf = 0; else
		currR->bf = 1;
	root->bf = 0;
}

图示过程:
在这里插入图片描述

完整插入代码

AVLTreeNode.h

#pragma once
#ifndef AVLTREENODE_H
#define AVLTREENODE_H
#include <iostream>
#include <vector>
using namespace std;
class AVLTreeNode
{
public:
	int val;
	int bf;		// 平衡因子
	AVLTreeNode* leftTree;
	AVLTreeNode* rightTree;
	AVLTreeNode() :val(0), bf(0), leftTree(NULL), rightTree(NULL) {}
	AVLTreeNode(int valable) :val(valable), bf(0), leftTree(NULL), rightTree(NULL) {}
	AVLTreeNode(int valable, int be, AVLTreeNode* lf, AVLTreeNode* rf) :val(valable), bf(be), leftTree(lf), rightTree(rf) {}
	AVLTreeNode* setAVLTree(vector<int> nums);
};
#endif // !AVLTREENODE_H

AVLTreeNode.cpp

#include "AVLTreeNode.h"
#include <iostream>
#include <stack>
#include <assert.h>
AVLTreeNode* AVLTreeNode::setAVLTree(vector<int> nums)
{
	AVLTreeNode* curr_fa = NULL, *root, *curr_ch;
	if (nums.empty())return NULL;
	root = new AVLTreeNode(nums[0]);
	curr_ch = root;
	stack<AVLTreeNode*>set_way_save;
	for (int i = 1; i < nums.size(); i++) {
		while (curr_ch)			// 查找应该插入的位置
		{
			if (nums[i] == curr_ch->val) {
				break;
				continue;
			}
			set_way_save.push(curr_ch);
			if (nums[i] < curr_ch->val)curr_ch = curr_ch->leftTree;
			else curr_ch = curr_ch->rightTree;
		}
		AVLTreeNode* node = new AVLTreeNode(nums[i]);
		curr_ch = set_way_save.top();
		if (node->val < curr_ch->val)
			curr_ch->leftTree = node;
		else
			curr_ch->rightTree = node;
		while (!set_way_save.empty()) {
			curr_ch = set_way_save.top();
			set_way_save.pop();
			if (curr_ch->leftTree == node)
				curr_ch->bf--;
			else
				curr_ch->bf++;
			if (curr_ch->bf == 0)break;
			else if (curr_ch->bf == 1 || curr_ch->bf == -1) {
				node = curr_ch;
			}
			else
			{
				if (curr_ch->bf < 0) {
					if (node->bf < 0)
						rotateRR(curr_ch);
					else
						rotateLR(curr_ch);
				}
				else {
					if (node->bf < 0)
						rotateRL(curr_ch);
					else
						rotateLL(curr_ch);
				}
				break;
			}
		}
	}
	return root;
}
void rotateLL(AVLTreeNode*& root) {
	AVLTreeNode* currL = root;
	root = currL->rightTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	root->bf = currL->bf = 0;
}
void rotateRR(AVLTreeNode*& root) {
	AVLTreeNode* curr = root;
	root = curr->leftTree;
	curr->leftTree = root->rightTree;
	root->rightTree = curr;
	root->bf = curr->bf = 0;
}
void rotateLR(AVLTreeNode*& root) {
	AVLTreeNode* currL = root->leftTree;
	AVLTreeNode* currR = root;
	root = currL->rightTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	if (root->bf <= 0)currL->bf = 0;
	else
		currL->bf = -1;

	currR->leftTree = root->rightTree;
	root->rightTree = currR;
	if (root->bf == -1)
		currR->bf = 1;
	else
		currR->bf = 0;
	root->bf = 0;
}
void rotateRL(AVLTreeNode*& root) {
	AVLTreeNode* currL = root;
	AVLTreeNode* currR = currL->rightTree;
	root = currR->leftTree;
	currL->rightTree = root->leftTree;
	root->leftTree = currL;
	if (root->bf == 1)
		currL->bf = -1;
	else
		currL->bf = 0;
	currR->leftTree = root->rightTree;
	root->rightTree = currR;
	if (root->bf >= 0)
		currR->bf = 0; else
		currR->bf = 1;
	root->bf = 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早安不安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值