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

相关推荐
AI科技星1 分钟前
宇宙的像素:真空中一点如何编码无限星光
数据结构·人工智能·算法·机器学习·重构
程芯带你刷C语言简单算法题4 分钟前
Day37~求组合数
c语言·开发语言·学习·算法·c
程序员-周李斌7 分钟前
transmittable-thread-local[线程池跨线程值传递]
java·开发语言·算法·散列表
Flash.kkl9 分钟前
优先算法专题十七——多源BFS
算法·宽度优先
Yzzz-F11 分钟前
牛客小白月赛 D[差分] E [暴力枚举] F[] g[二阶差分]
算法
liliangcsdn12 分钟前
DDPM前向加噪过程详细推导
人工智能·算法·机器学习
没有bug.的程序员30 分钟前
Sentinel 流控原理深度解析:构建高可用微服务的底层架构
java·算法·微服务·云原生·架构·sentinel·负载均衡
深圳佛手30 分钟前
IVFFlat 与 HNSW 算法介绍与对比
人工智能·算法·机器学习
Q741_14734 分钟前
C++ 栈 模拟 力扣 227. 基本计算器 II 题解 每日一题
c++·算法·leetcode·模拟
徐新帅37 分钟前
CSP 二进制与小数进制转换专题及答案解析
c++·算法