数据结构 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

相关推荐
孞㐑¥18 分钟前
算法——BFS
开发语言·c++·经验分享·笔记·算法
月挽清风23 分钟前
代码随想录第十五天
数据结构·算法·leetcode
XX風39 分钟前
8.1 PFH&&FPFH
图像处理·算法
NEXT061 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法
代码游侠1 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
想进个大厂1 小时前
代码随想录day37动态规划part05
算法
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章22-Harris角点
图像处理·人工智能·opencv·算法·计算机视觉
子春一2 小时前
Flutter for OpenHarmony:构建一个 Flutter 四色猜谜游戏,深入解析密码逻辑、反馈算法与经典益智游戏重构
算法·flutter·游戏
人道领域2 小时前
AI抢人大战:谁在收割你的红包
大数据·人工智能·算法
TracyCoder1232 小时前
LeetCode Hot100(34/100)——98. 验证二叉搜索树
算法·leetcode