数据结构 AVL二叉平衡树

cpp 复制代码
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<iostream>
#include <stack>
using namespace std;
typedef int ELEMTYPE;

typedef struct AVLNode{
	ELEMTYPE val;
	struct AVLNode* leftchild;
	struct AVLNode* rightchild;
	//用递归实现 双亲就不需要了
	int height;//节点的高度  防止bst退化
}AVLNode;

//辅助节点
typedef struct AVLTree{
	AVLNode* root;
}AVLTree;

//1.购买新节点
AVLNode* BuyNode(int val) {
	AVLNode* p = (AVLNode*)malloc(sizeof(AVLNode));
	if (p == nullptr) {
		cout << "init err" << endl;
		return nullptr;
	}
	p->height = 0;
	p->leftchild = p->rightchild = 0;
	p->val = val;
	return p;
}

//2.获取当前节点的高度
int Get_Height(AVLNode* Node) {
	if (Node == nullptr)return -1;
	return Node->height;
}

//3.更新当前节点的高度
void Update_Height(AVLNode* Node) {
	assert(Node != nullptr);
	int lh = Get_Height(Node->leftchild);
	int rh = Get_Height(Node->rightchild);
	Node->height = lh > rh ? lh + 1 : rh + 1;
}

//4.获取当前节点的平衡因子
int Get_BalanceFactor(AVLNode* Node) {
	assert(Node != nullptr);
	if (Node == nullptr)return 0;
	int lh = Get_Height(Node->leftchild);
	int rh = Get_Height(Node->rightchild);
	return lh - rh;
}


//5.左旋  将冲突节点旋转到自己右孩子的左边 
// 要是右孩子左边有节点了就存一下那个节点先把冲突节点安置好再插回去
AVLNode* Left_Rotate(AVLNode* node) {
	assert(node != nullptr);
	AVLNode* child = node->rightchild;
	AVLNode* temp = child->leftchild;		
	child->leftchild = node;
	node->rightchild = temp;
	Update_Height(node);
	Update_Height(child);
	return child;
}

//6.右旋  将冲突节点旋转到自己左孩子的右边 
// 要是左孩子右边有节点了就存一下那个节点先把冲突节点安置好再插回去
AVLNode* Right_Rotate(AVLNode* node) {
	assert(node != nullptr);
	AVLNode* child = node->leftchild;
	AVLNode* temp = child->rightchild;
	child->rightchild = node;
	node->leftchild = temp;
	Update_Height(node);
	Update_Height(child);
	return child;
}

//7.通用的旋转函数(接收接收node,对node进行判断,如果没有
// 失衡,则不用调整最直接退出,反之如果失衡,则调整好再退出)
AVLNode* Rotate(AVLNode* node) {
	assert(node != nullptr);
	int ba = Get_BalanceFactor(node);
	if (ba == 2){//L  如果失衡 那么一定是2/-2
		//2.再用一个变量,用来保存node节点的左孩子的平衡因子
		int ba_leftchild = Get_BalanceFactor(node->leftchild);
		if (ba_leftchild == 1 || ba_leftchild == 0){//LL型
			return Right_Rotate(node);
		}
		if (ba_leftchild == -1){//LR
			//先左旋 //是对失衡节点的左孩子说的
			node->leftchild = Left_Rotate(node->leftchild);
			//再右旋 //是对失衡节点自身说的
			return Right_Rotate(node);
		}
	}
	if (ba == -2){//R
		//3..再用一个变量,用来保存node节点的右孩子的平衡因子
		int ba_rightchild = Get_BalanceFactor(node->rightchild);
		if (ba_rightchild == -1 || ba_rightchild == 0){//RR
			//单左旋完成
			return Left_Rotate(node);
		}
		if (ba_rightchild == 1){//RL
			//先右旋 //是对失衡节点的右孩子说的
			node->rightchild = Right_Rotate(node->rightchild);
			//再左旋 //是对失衡节点自身说的
			return Left_Rotate(node);
		}
	}
	return node;
}


//普通函数
//1.初始化
void Init_AVLTree(AVLTree* pTree) {
	assert(pTree != nullptr);
	pTree->root = nullptr;
}

//2.插入(启动函数)
bool Insert_AVL(AVLTree* pTree, ELEMTYPE val) {
	assert(pTree != nullptr);
	pTree->root = Insert_Helper(pTree->root, val);
	return true;
}
//2.5 插入函数的递归函数
AVLNode* Insert_Helper(AVLNode* root, ELEMTYPE val) {
	if (root == nullptr){
		AVLNode* pnewnode = BuyNode(val);
		return pnewnode;
	}

	//判断当前root指向的节点的数据域 是等于val/大于val/小于val
	if (val == root->val){
		return root;
	}
	if (val < root->val){
		root->leftchild = Insert_Helper(root->leftchild, val);
	}
	else{
		root->rightchild = Insert_Helper(root->rightchild, val);
	}
	Update_Height(root);
	root = Rotate(root);//Rotate 去修root修复   从上至下
	return root;
}



//3.删除(启动函数)
bool Delete_AVL(AVLTree* pTree, ELEMTYPE val) {
	assert(pTree != nullptr);
	pTree->root = Delete_Helper(pTree->root, val);
	return true;
}
//3.5 删除函数的递归函数
AVLNode* Delete_Helper(AVLNode* root, ELEMTYPE val) {
	if (root == nullptr)return nullptr;
	if (val < root->val){
		root->leftchild = Delete_Helper(root->leftchild, val);
	}
	else if (val > root->val){
		root->leftchild = Delete_Helper(root->rightchild, val);
	}
	else{//找到了
		AVLNode* temp = root;
		AVLNode* child = nullptr;
		//是双分支情况
		if (root->leftchild  && root->rightchild ){
			temp = temp->rightchild;
			while (temp->leftchild) temp = temp->leftchild;
			root->val = temp->val;
			root->rightchild = Delete_Helper(root->rightchild, temp->val);
		}
		else{
			//无叶子节点
			if (root->leftchild)//只有左孩子 
				child = temp->leftchild;
			else //只有右孩子/无孩子(child=nullptr
				child = temp->rightchild;
			free(root);
			return child;
		}
	}
	//更新当前节点
	Update_Height(root);
	//再将此时的root扔到通用旋转函数里,出来后肯定是平衡的,直接返回即可
	return Rotate(root);
}



//4.查找
AVLNode* Search_AVL(AVLNode* root, ELEMTYPE val) {
	if (root == nullptr)return nullptr;
	AVLNode* temp = root;
	while (temp) {
		if (val > temp->val)temp = temp->rightchild;
		else if (val < temp->val)temp = temp->leftchild;
		else return temp;
	}return nullptr;
}

//5.打印 中序遍历
void Show_InOrder(AVLNode* root) {
	assert(root != nullptr);
	AVLNode* temp = root;
	stack<AVLNode*>st1;
	while (!st1.empty() || temp) {
		while (temp) {
			st1.push(temp);
			temp = temp->leftchild;
		}
		temp = st1.top();
		st1.pop();
		cout << temp->val << " ";
		temp = temp->rightchild;
	}
	cout << endl;
}


int main() {


	return 0;
}

理解左旋右旋那些点之后就不难了qvq

相关推荐
带鱼吃猫5 小时前
数据结构:顺序表与基于动态顺序表的通讯录项目
数据结构·链表
l1t5 小时前
利用Duckdb求解Advent of Code 2025第5题 自助餐厅
数据库·sql·mysql·算法·oracle·duckdb·advent of code
List<String> error_P5 小时前
C语言枚举类型
算法·枚举·枚举类型
liu****5 小时前
20.预处理详解
c语言·开发语言·数据结构·c++·算法
努力学算法的蒟蒻5 小时前
day26(12.6)——leetcode面试经典150
算法·leetcode·面试
代码游侠5 小时前
数据结构——哈希表
数据结构·笔记·学习·算法·哈希算法·散列表
FY_20185 小时前
Stable Baselines3中调度函数转换器get_schedule_fn 函数
开发语言·人工智能·python·算法
CoderYanger6 小时前
动态规划算法-子数组、子串系列(数组中连续的一段):26.环绕字符串中唯一的子字符串
java·算法·leetcode·动态规划·1024程序员节
Jane-6667776 小时前
C语言——表达式、语句、函数
c语言·开发语言·算法