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;
}