【数据结构】AVL树insert接口实现

AVL树的插入接口需要分多种情况讨论,
前提是依据插入后平衡因子的值来做调整:

1.平衡因子为0,结束调整;
2.平衡因子为正负1,继续向上调整,直到0;
3.平衡因子为正负2,此时还需要进一步讨论:

出现平衡因子±2比较复杂,需要针对每一种情况做出不同旋转:

3.1. pParent的平衡因子为2,说明pParent的右子树高,设pParent的右子树的根为pSubR
当pSubR的平衡因子为1时,执行左单旋
当pSubR的平衡因子为-1时,执行右左双旋
3.2. pParent的平衡因子为-2,说明pParent的左子树高,设pParent的左子树的根为pSubL
当pSubL的平衡因子为-1是,执行右单旋
当pSubL的平衡因子为1时,执行左右双旋
旋转完成后,原pParent为根的子树个高度降低,已经平衡,不需要再向上更新。

#include<iostream>
using namespace std;
template<class T>
//AVLTree节点
class AVLNode{
public:
	//AVL数有3个节点指针,1个val,1个平衡因子
	int _bf;
	T _val;
	AVLNode<T>* _partent;
	AVLNode<T>* _left;
	AVLNode<T>* _right;

	AVLNode(const T& val = T())//类0值
		:_bf(0)
		, _val(val)
		, _partent(nullptr)
		, _left(nullptr)
		, _right(nullptr)	
		{}
};
//AVLTree树
template<class T>
class AVLTree{
public:
	typedef AVLNode<T> Node;

	bool insert(const T& val){
		//先判断是否为空树
		if (_root == nullptr){
			_root = new Node(val);
			return true;
		}
		Node* node=_root;
		Node* partent=nullptr;
		while (node){
			partent = node;
			if (node->_val == val){
				return false;
			}
			else if (node->_val > val){
				node = node->_left;
			}
			else{
				node = node->_right;
			}
		}
			//此时node在空上,并且没有链接父节点
			node = new Node(val);
			//此时链接父节点
			if (partent->_val>val){
				partent->_left = node;
			}
			else{
				partent->_right = node;
			}
			node->_partent = partent;

			//开始调整bf
			//从partent开始
			while (partent){
				//先对父节点bf进行增或减
				if (partent->_left == node)
					--partent->_bf;
				else
					++partent->_bf;
				//根据调整后的bf操作
				//bf==0,结束调整
				//bf=+-1,继续向上更新
				//bf=+-2,需要旋转
				if (partent->_bf == 0){
					break;
				}
				else if (partent->_bf == 1 || partent->_bf == -1){
					node = partent;
					partent = partent->_partent;
				}
				else if(abs(partent->_bf)==2){
					if (node->_bf == -1 && partent->_bf == -2){
						//需要右旋
						RotateR(partent);
					}
					else if (node->_bf == 1 && partent->_bf == 2){
						RotateL(partent);
					}
					else if (partent->_bf == 2 && node->_bf == -1){
						Node* subRL = node->_left;
						int bf = subRL->_bf;
						RotateR(node);
						RotateL(partent);
						if (bf == 1){
							partent->_bf = -1;
							node->_bf = 0;
						}
						else if (bf == -1){
							node->_bf = 1;
							partent->_bf = 0;

						}
					}
					else if (partent->_bf == -2 && node->_bf == 1){
						Node* subLR = node->_right;
						int bf = subLR->_bf;
						RotateL(node);
						RotateR(partent);
						if (bf == 1){
							partent->_bf = 0;
							node->_bf = -1;
						}
						else if (bf == -1){
							node->_bf = 0;
							partent->_bf = 1;

						}
					}
					break;
				}
			
		}
		return true;
	}
	//				partent              subL
	//subL                      ->				partent
	//		subLR							subLR								
	void RotateR(Node* partent){
		Node* subL = partent->_left;
		Node* subLR = subL->_right;
		subL->_right = partent;
		partent->_left = subLR;
		if (subLR){
			subLR->_partent = partent;
		}

		
		//调整上部节点
		if (partent == _root){
			_root = subL;
			subL->_partent = nullptr;
		}
		else{
			Node* pparent = partent->_partent;
			if (pparent->_left == partent){
				pparent->_left = subL;
			}else{
				pparent->_right = subL;
			}
			subL->_partent = pparent;
		}
		partent->_partent = subL;
		subL->_bf = partent->_bf = 0;
	}

	//partent                                     subR
	//            subR        ->	partent
	//		subRL							subRL								
	void RotateL(Node* partent){
		Node* subR = partent->_right;
		Node* subRL = subR->_left;
		subR->_left = partent;
		partent->_right = subRL;
		if (subRL){
			subRL->_partent = partent;
		}

		partent->_partent = subR;
		//调整上部节点
		if (partent == _root){
			_root = subR;
			subR->_partent = nullptr;
		}
		else{
			Node* pparent = partent->_partent;
			if (pparent->_left == partent){
				pparent->_left = subR;
			}
			else{
				pparent->_right = subR;
			}
			subR->_partent = pparent;
		}
		subR->_bf = partent->_bf = 0;
	}

	void _inorder(Node* root){
		if (root){
			_inorder(root->_left);
			cout << root->_val << " ";
			_inorder(root->_right);
		}
	}
	void inorder(){
		return _inorder(_root);
	}

	//检查AVL是否正确
	//查看节点长度
	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 << root->_val <<":错误"<< endl;
			return false;
		}

		return abs(root->_bf) < 2 && _isbalance(root->_left) && _isbalance(root->_right);

	}

	bool isbalance(){
		return _isbalance(_root);
	}
private:
	//记得置空
	AVLNode<T>* _root=nullptr;

};

void test(){
	AVLTree<int> t;
	t.insert(5);
	t.insert(3);
	t.insert(1);
	t.insert(0);
	t.insert(2);
	t.insert(-1);
	t.insert(5);
	t.insert(1);
	t.inorder();
	cout << endl;
	cout<<t.isbalance();
}
int main(){
	test();
	system("pause");
	return 0;
}

通过校验:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值