首页 > 其他 > 详细

二叉平衡树

时间:2019-02-28 13:43:37      阅读:161      评论:0      收藏:0      [点我收藏+]
#include "MyAVLTree.h"
#include <iostream>


MyAVLTree::MyAVLTree()
{
	root_ = nullptr;
}


MyAVLTree::~MyAVLTree()
{
}


void MyAVLTree::UpdateDepth(MyTNode *node)
{
	if (node == nullptr)
		return;
	int l_depth = node->lchild == nullptr ? 0 : node->lchild->depth;
	int r_depth = node->rchild == nullptr ? 0 : node->rchild->depth;
	node->depth = (l_depth > r_depth ? l_depth : r_depth) + 1;
}


int MyAVLTree::GetBF(MyTNode *node)
{
	int l_depth = node->lchild==nullptr?0: node->lchild->depth;
	int r_depth = node->rchild == nullptr ? 0 : node->rchild->depth;
	return l_depth - r_depth;
}

//左旋转本质:
//node变成其右子节点的左子节点
//node的右子节点的左子节点变成node的右子节点
MyTNode* MyAVLTree::L_Rotate(MyTNode*node)
{
	//第一步 交换N和R的值
	auto r_child = node->rchild;
	{
		auto tmp = node->value;
		node->value = r_child->value;
		r_child->value = tmp;
	}

	//第二步 N和R指针互换
	{
		auto tmp = r_child;
		r_child = node;
		node = tmp;
	}

	//第三步  做空N节点  r_child与r_child->r_child->r_child直连 跳过node
	r_child->rchild = node->rchild;
	if(node->rchild!=nullptr)
		node->rchild->parent = r_child;

	//第四步  node的左节点变成node的右节点
	node->rchild = node->lchild;

	//第五步 如果r_child拥有左节点X,node的左节点赋值为X
	if (r_child->lchild != nullptr)
	{
		node->lchild = r_child->lchild;
		r_child->lchild->parent = node;
	}

	//第六步 r_child左节点赋值为node
	r_child->lchild = node;
	node->parent = r_child;
	return node;
}


MyTNode* MyAVLTree::R_Rotate(MyTNode*node)
{
	//auto parent = node->parent;
	auto l_child = node->lchild;

	//第一步交换 node 和其左孩子的值
	//这个时候node变成了原来的左孩子   左孩子l_child变成了node
	//下面操作node,其实已经是新的node了,即为l_child
	auto tmp = node->value;
	node->value = l_child->value;
	l_child->value = tmp;
	{
		auto tmp = node;
		node = l_child;
		l_child = tmp;
	}
	//
	if (l_child->lchild != nullptr)
	{
		l_child->lchild = node->lchild;
		if(node->lchild!=nullptr)
			node->lchild->parent = l_child;
	}

	//
	
	node->lchild = node->rchild;
	node->rchild = l_child->rchild;
	if (l_child->rchild != nullptr)
	{
		l_child->rchild->parent = node;
		l_child->rchild = node;
	}
	node->parent = l_child;
	l_child->rchild = node;
	return node;
}

void MyAVLTree::AVLTree(MyTNode *node)
{
	int bf = 0;//平衡因子
	while (node != nullptr)
	{
		UpdateDepth(node);
		bf = GetBF(node);
		//说明已经不平衡了!!!!
		if (bf > 1 || bf < -1)
		{
			//左子树高
			if (bf > 1)
			{
				int l_bf = GetBF(node->lchild);
				if (l_bf > 0)//LL型
				{
					//需要重新计算深度
					node = R_Rotate(node);
					continue;
				}
				else//LR型
				{
					node = L_Rotate(node->lchild);
					//R_Rotate(node);
					//node = tmp;
					continue;
				}
			}
			if (bf < -1)
			{
				int l_bf = GetBF(node->rchild);
				if (l_bf <0)//RR型
				{
					//需要重新计算深度
					node = L_Rotate(node);
					continue;
				}
				else//RL型
				{
					//需要重新计算深度
					node = R_Rotate(node->rchild);
					continue;
				}
			}
			//需要调整
		}
		node = node->parent;
	}
}

void MyAVLTree::Insert(int val)
{
	//返回插入节点所在位置,按二叉排序树的简单插入
	MyTNode* node = InsertVal(root_, root_, val);
	//更新深度
	UpdateDepth(node);
	//二叉树的平衡调整,里面会递归更新每个节点的深度
	AVLTree(node);
}

void MyAVLTree::PrintLastOrder(MyTNode *node)
{
	if (node == nullptr)
		return;
	
	PrintLastOrder(node->lchild);
	PrintLastOrder(node->rchild);
	std::cout << node->value << std::endl;
}
void MyAVLTree::PrintMidOrder(MyTNode *node)
{
	if (node == nullptr)
		return;

	std::cout << node->value << std::endl;
	PrintMidOrder(node->lchild);
	PrintMidOrder(node->rchild);
}

void MyAVLTree::PrintPreOrder(MyTNode *node)
{
	if (node == nullptr)
		return;
	PrintPreOrder(node->lchild);
	std::cout << node->value << std::endl;
	PrintPreOrder(node->rchild);
}

MyTNode* MyAVLTree::InsertVal(MyTNode* &node, MyTNode* &parent, int val)
{
	if(node == nullptr)
	{
		if (parent == nullptr)
		{
			node = new MyTNode();
			node->value = val;
			node->parent = nullptr;
			return node;
		}
		node = new MyTNode();
		node->value = val;		
		node->parent = parent;
		return node;
	}
	if (node->value > val)
	{
		return InsertVal(node->lchild, node, val);
	}
	else
	{
		return InsertVal(node->rchild, node, val);
	}
}

  重点:

  1. 左旋和右旋的含义:举例子,左旋就是让node节点的右子节点,成为node的父节点,node为其左节点
  2. AVL调整的过程在,先按二叉排序树的插入,然后往上递归父节点,重新计算平衡值,如果node平衡值Abs绝对值大于1,说明不平衡,再对比其子节点的平衡值,确认是LL LR RL RR哪种类型!

二叉平衡树

原文:https://www.cnblogs.com/shawnc24/p/10449280.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!