C++实现平衡二叉树

平衡二叉树实现准备工作

要实现二叉树,首先要对其节点和树结构进行定义;

节点结构体

`template<class T>
struct Node {
	T key;
	Node<T>* lchild;
	Node<T>* rchild;
	Node<T>(T k) : key(k), lchild(nullptr), rchild(nullptr) {}
};`

平衡二叉树类实现

template<class T>
class AVLTree {
private:
	Node<T>* root;
public:
	AVLTree() :root(nullptr) {};
	Node<T>* getRoot() { return root; }
	Node<T>* llRotation(Node<T>*);
	Node<T>* lrRotation(Node<T>*);
	Node<T>* rrRotation(Node<T>*);
	Node<T>* rlRotation(Node<T>*);
	void balance(Node<T>*)void fixUp();  //修复平衡
};

具体操作实现过程

对应图解可参考https://blog.csdn.net/qq_40738840/article/details/86501072

ll型(即插入节点在左子树的左子树上,对应右旋操作

template<class T>
Node<T>* AVLTree<T>::llRotation(Node<T>* node) {  //插入节点在左子树左边,右旋
	Node<T>* temp = node->lchild;
	node->lchild = temp->rchild;
	temp->rchild = node;
	return temp;
}

rr型(即插入节点在右子树的右子树上,对应左旋操作

template<class T>
Node<T>* AVLTree<T>::rrRotation(Node<T>* node) {  //插入节点在右子树左边,左旋
	Node<T>* temp = node->rchild;
	node->rchild = temp->lchild;
	temp->lchild = node;
	return temp;
}

lr型(即插入节点在左子树的右子树上,对应先左旋再右旋操作

template<class T>
Node<T>* AVLTree<T>::lrRotation(Node<T>* node) {  //插入节点在左子树右边
	Node<T>* temp = node->lchild;
	node->lchild = rrRotation(temp);
	return llRotation(node);
}
}

需要注意的是,此时的先左旋再右旋是相对于整颗二叉树而言的,但是在插入结点后我们的操作一般是先处理靠近节点的一个父亲节点,所以是先相对于新插入节点而被破坏平衡的节点进行左旋操作,故而lr型的第三行代码是调用rrRotation方法。

rl型(即插入节点在右子树的左子树上,对应先左旋再右旋操作

template<class T>
Node<T>* AVLTree<T>::rlRotation(Node<T>* node) {  //插入节点在右子树左边
	Node<T>* temp = node->rchild;
	node->rchild = llRotation(temp);
	return rrRotation(node);
}

平衡函数实现

template<class T>
void AVLTree<T>::balance(Node<T>* node) {
	int bf = getBalanceFactor(node);
	if (bf > 1) {
		if (getBalanceFactor(node->lchild) > 0)
			root = llRotation(node);
		else
			root = lrRotation(node);
	}
	else if (bf < -1) {
		if (getBalanceFactor(node->rchild) > 0)
			root = rlRotation(node);
		else
			root = rrRotation(node);
	}
	return;
}

template<class T>
void AVLTree<T>::fixUp() {
	Node<T>* temp = this->root;  //自顶向下调整树
	while (1)  //寻找失衡的节点
	{
		if (getBalanceFactor(temp) == 2) {
			if (fabs(getBalanceFactor(temp->lchild)) == 1)
				break;
			else
				temp = temp->lchild;
		}
		else if (getBalanceFactor(temp) == -2) {
			if (fabs(getBalanceFactor(temp->rchild)) == 1)
				break;
			else
				temp = temp->rchild;
		}
		else break;
	}
	balance(temp);
	return;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值