AVL2

//红黑树
//AVL树 平衡的二叉搜索树
//平衡因子 每个节点的左右子树的高度差
template
struct AVLNode
{

AVLNode<T>* _Left; // 该节点的左孩子
AVLNode<T>* _Right; // 该节点的右孩子
AVLNode<T>* _Parent; // 该节点的双亲
T _val;
int _bf; // 该节点的平衡因子

AVLNode(const T& _data = T())
	:_pParent(nullptr)
	, _Left(nullptr)
	, _Right(nullptr)
	, _val(val)
	, _bf(0)
{}

};

template
class AVLTree
{
public:
typedef AVLNode Node;

//插入的接口
bool insert(const T& val)
{
//二叉搜索树插入
	//现在是空树,可以直接进行插入
	if (_root == nullptr)
	{
		_root = new Node(val);
		return true;
	}

	//_root
	//*****************
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		parent = cur;
		//判断插入的值是否是已经存在的。
		if (cur->_val == val)
			return false;
		//使用的还是搜索二叉树的节奏就是左小右大
		else if (cur->_val > val)
			cur = cur->_left;
		else
			cur = cur->_right;
	}

	//平衡因子的调整
	cur = new Node(val)
		if (parent->_val > val)
			parent->_left = cur;
		else
			parent->_right = cur;
	cur->_parent = parent;

	//调整  从parent开始
	if (parent->_left == cur)
		--parent->_bf;
	else
		++parent->_bf;

	//更新父节点的平衡因子
	while (parent)
	{
    if(parent->_bf==0)  //parent的比较短的子树高度+1
	//结束更新
	else if (parent->_bf == 1 || parent->_bf == -1)
		//继续向上更新
	{
		//更新调整位置
		cur = parent;
		parent = parent->_parent;
	}


	//下边的情况就是表示的是需要对结构进行操作的情况(就是平衡因子更新的根节点时候,根节点的平衡因子已经是不平衡的)
	//使用的方法是旋转  目的通过调整结构就是让平衡因子缩小在范围控制(0-->+/-2)
	//旋转的实现是通过修改指针的指向来实现的。

	//****注意旋转的开始的点是-2/+2的点进行开始****
	else if (abs(parent->_bf) == 2)
	{
		if(parent->_bf) == -2&&cur->_bf==-1)
		{
		//左边的左边高、
		//右旋
		RotateR(parent);
        }
		else if (parent->_bf == 2 && cur->_bf == 1)
		{
			//右边的右边高
			RotateL(parent);
		}
		else if(parent->_bf) == -2 && cur->_bf == 1)
		{
		Node* subLR = cur->_right;
		int bf = subLR->_bf;

		RotateL(cur);
		RotateR(parent);
		if (bf == 1)
		{
			parent->_bf = 0;
			cur->_bf=-1
		}
		else if (bf == -1)
		{
			parent->_bf = 1;
			cur->_bf = 0;
		}
        }
		else if (parent->_bf) == 2 && cur->_bf == -1)
		{
		//保存节点的平衡因子(subRL)
		Node* subLR = cur->_right;
		int bf = subLR->_bf;

}
//注意的就是双旋的特征 注意旋转的起始位置,以及第一次旋转完成之后还要进行的操作。
//双旋 左边的右边高
//双旋的特点
//左边的右边高 双旋
//1.以cur为轴,进行左旋
//2.以parent为轴,进行性右旋
//先左旋再右旋
else if (parent->_bf == -2 && cur->_bf == 1)
{
RotateL(cur);
RotateR(parent);
}

		//右边的左边高
		//parent:2 cur:-1
		//右边的左边高
		//右左双旋;
		//1.以cur为轴进行右旋
		//2.parent为轴,进行左旋
		else if (parent->_bf == 2 && cur->_bf == -1)
		{
			//保存右左平衡因子
			Node* subRL = cur->_Left;
			int bf = subRL->_bf;
			RotateR(cur);
			RotateL(parent);

			//修正平衡因子
			if (bf == 1)
			{
				cur->_bf = 0;
				parent->_bf = -1;

			}
			else if (bf == -1)
			{
				cur->_bf = 1;
				parent->_bf = 0;
			}
		}
	}
	break;
	}
}
//插入成功
return true;

//右旋转
//          parent
//    subL
//          subLR

void RotateR((Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;

	subL->_right = parent;
	parent->_left = subLR;

	if (subLR)
		subLR->_parent = parent;

	//判断parent是不是根节点
	if (parent == _root)
	{
		//根节点
		_root = subL;
		subL->_parent = nullptr;
	}
	else
	{
     Node* pparent = parent->_parent;
	if (pparent->_left == parent)
		pparent->_left = subL;
	else
		pparent->_right = subL;
	subL->_parent = pparent;

	
	}
	parent->_parent = subL;

	subL->_bf = parent->_bf = 0;
}


//注意旋转的话一定注意大方向的把握。才能书写正确的代码
//左旋
//  parent
//                  subR
//        subL
void RotateL((Node* parent)
{
	Node* subR=parent->_right;
	Node* subRL =subR->_left;

	subR->_left = parent;
	parent->_right = subRL;

	if (subRL)
		subRL->_parent = parent;

	//判断parent是不是根节点
	if (parent == _root)
	{
		//根节点
		_root = subR;
		subR->_parent = nullptr;
	}
	else
	{
		Node* pparent = parent->_parent;
		if (pparent->_left == parent)
			pparent->_left = subR;
		else
			pparent->_right = subR;
		subR->_parent = pparent;
	}
	parent->_parent = subR;
	//更新平衡因子。
	subL->_bf = parent->_bf = 0;
}

//使用中序遍历去验证是不是还是一个搜索树
void inorder()
{
	_inorder(_root);
}

void _inorder(Node* root)
{
	if (root)
	{
		_inorder(root->_Left);
		cout << root->_val << " ";
		_inorder(root->_Right);
	}
}


//获取高度
int Height(Node* root)
{
	if (root == nullptr)
		return 0;
	int left = Height(root->_left);
	int right = Height(root->_Right);
	return left > Right ? left + 1:right+1;

}
//验证平衡的是不是
bool _isBalance(Node* root)
{
	if (root == nullptr)
		return true;
	//查看平衡因子是否是左右子树的高度差一致
	int left = Height(root->_Left);
	int right = Height(root->_right);
	if (right - left != root->_bf)
	{
		cout << "Node:" << root->_val << "bf:" << root->_bf << "height gap" << right - left << endl;
		return false;
	}
	return abs(root->_bf) < 2
		&& _isBalance(root->_left)
		&& _isBalance(root->_Right);
}

private:
Node* _root = nullptr;
};

void test()
{
AVLTree avl;
avl.insert(5);
avl.insert(3);
avl.insert(2);
avl.insert(1);
avl.insert(0);
avl.insert(-1);
avl.insert(15);
avl.insert(10);
avl.insert(20);
avl.insert(13);
avl.insert(25);
}

//测试使用随机值
void test1()
{
srand(time(nullptr));
cout << “num:” << endl;
int num;
cin >> num;
AVLTree avl;
for (int i = 0; i < num; ++i)
{
avl.insert(rand());

}
avl.inorder();

}

int main()
{
test();
test1();
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值