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

相关推荐
lcj25111 分钟前
【C语言】自定义类型1:结构体
c语言·开发语言·算法
jaysee-sjc4 分钟前
十七、Java 高级技术入门全解:JUnit、反射、注解、动态代理
java·开发语言·算法·junit·intellij-idea
yongui478346 分钟前
MATLAB模糊控制的粒子群算法(Fuzzy-PSO)实现
数据结构·算法·matlab
sali-tec7 分钟前
C# 基于OpenCv的视觉工作流-章49-人脸检测
图像处理·人工智能·opencv·算法·计算机视觉
不爱吃炸鸡柳8 分钟前
4道经典算法题代码详解:从两数之和到链表两两交换
算法·链表·哈希算法
cmpxr_13 分钟前
【C】隐式类型转换
c语言·c++·算法
W230357657314 分钟前
【C++ 高性能日志系统实战】第三篇:异步日志系统的实现与优化
网络·数据结构·算法·日志
y = xⁿ21 分钟前
【LeetCode】哈希表
算法·leetcode·散列表
智者知已应修善业28 分钟前
【51单片机独立按键控制数码管动态显示和LED间隔闪烁并清零】2023-5-28
c语言·经验分享·笔记·算法·51单片机