之前介绍了如何添加的元素位于不平衡节点左侧的左侧及右侧的右侧时如何处理,那么这篇首先介绍如何解决添加元素位于不平衡节点左侧的右侧及右侧的左侧该怎么处理。
LR
插入节点z位于x的右侧,此时问题比之前复杂一点,一次旋转并不能解决问题。因为
T
1
<
x
<
T
2
<
z
<
T
3
<
y
<
T
4
T1<x<T2<z<T3<y<T4
T1<x<T2<z<T3<y<T4,将x先进行左旋转。此时的情况就和之前右旋转的情况一致,只需要对y进行一次右旋转即可。
RL
那么另外一种情况也就很好理解了,只需要先对x进行一次右旋转,然后再对y进行一次左旋转即可。
删除元素
删除元素时,只需要对节点高度更新即可。因为删除元素时也是采用递归方法,所以更新高度的方法和添加节点时一样。
实现
实现时采用的主要代码还是之前二分搜索树的代码。
#include <iostream>
#include <queue>
#include <cassert>
#include <cmath>
#include <algorithm>
using namespace std;
// AVL树
template <typename Key, typename Value>
class AVLTree{
private:
// 树中的节点为私有的结构体, 外界不需要了解树节点的具体实现
struct Node{
Key key;
Value value;
Node *left;
Node *right;
int height;
Node(Key key, Value value){
this->key = key;
this->value = value;
this->left = this->right = NULL;
height = 1;
}
Node(Node *node){
this->key = node->key;
this->value = node->value;
this->left = node->left;
this->right = node->right;
}
};
Node *root; // 根节点
int count; // 树中的节点个数
public:
// 构造函数, 默认构造一棵空AVL树
AVLTree(){
root = NULL;
count = 0;
}
// 析构函数, 释放AVL树的所有空间
~AVLTree(){
destroy( root );
}
// 返回AVL树的节点个数
int size(){
return count;
}
// 返回AVL树是否为空
bool isEmpty(){
return count == 0;
}
// 向AVL树中插入一个新的(key, value)数据对
void insert(Key key, Value value){
root = insert(root, key, value);
}
// 查看AVL树中是否存在键key
bool contain(Key key){
return contain(root, key);
}
// 在AVL树中搜索键key所对应的值。如果这个值不存在, 则返回NULL
Value* search(Key key){
return search( root , key );
}
// AVL树的前序遍历
void preOrder(){
preOrder(root);
}
// AVL树的中序遍历
void inOrder(){
inOrder(root);
}
// AVL树的后序遍历
void postOrder(){
postOrder(root);
}
// AVL的层序遍历
void levelOrder(){
queue<Node*> q;
q.push(root);
while( !q.empty() ){
Node *node = q.front();
q.pop();
cout<<node->key<<endl;
if( node->left )
q.push( node->left );
if( node->right )
q.push( node->right );
}
}
// 寻找AVL树的最小的键值
Key minimum(){
assert( count != 0 );
Node* minNode = minimum( root );
return minNode->key;
}
// 寻找AVL树的最大的键值
Key maximum(){
assert( count != 0 );
Node* maxNode = maximum(root);
return maxNode->key;
}
// 从AVL树中删除最大值所在节点
void removeMax(){
if( root )
root = removeMax( root );
}
// 从AVL树中删除键值为key的节点
void remove(Key key){
root = remove(root, key);
}
//判断是否为平衡二叉树
bool isBalanced(){
return isBanlanced(root);
}
private:
bool isBanlanced(Node* node){
if (node == NULL)
return true;
int balanceFactor = getBalanceFactor(node);
if (abs(balanceFactor) > 1)
return false;
return isBalanced(node->left) && isBalanced(node->right);
}
//计算平衡因子
int getBalanceFactor(Node* node){
if (node == NULL)
return 0;
return getHeight(node->left) - getHeight(node->right);
}
//获取节点的高度
int getHeight(Node* node){
if (node == NULL)
return 0;
return node->height;
}
// 向以node为根的AVL树中, 插入节点(key, value), 使用递归算法
// 返回插入新节点后的AVL树的根
Node* insert(Node *node, Key key, Value value){
if( node == NULL ){
count ++;
return new Node(key, value);
}
if( key == node->key )
node->value = value;
else if( key < node->key )
node->left = insert( node->left , key, value);
else // key > node->key
node->right = insert( node->right, key, value);
//更新节点高度
node->height = 1 + max(getHeight(node->left), getHeight(node->right));
int balanceFactor = getBalanceFactor(node);
//维护树的平衡
if (balaceFactor >1 && getBalanceFactor(node->left) >= 0)
node = rightRotate(node);
if (balaceFactor <-1 && getBalanceFactor(node->right) <= 0)
node = leftRotate(node);
if (balaceFactor >1 && getBalanceFactor(node->left) < 0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
if (balaceFactor < -1 && getBalanceFactor(node->right) > 0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
//右旋转
Node* rightRotate(Node* y){
Node* x = y->left;
Node* T3 = x->right;
x->right = y;
y->left = T3;
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;//x位于y上层,在y后更新
return x;
}
//左旋转
Node* leftRotate(Node* y){
Node* x = y->right;
Node* T3 = x->left;
x->left = y;
y->right = T3;
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;//x位于y上层,在y后更新
return x;
}
// 查看以node为根的AVL树中是否包含键值为key的节点, 使用递归算法
bool contain(Node* node, Key key){
if( node == NULL )
return false;
if( key == node->key )
return true;
else if( key < node->key )
return contain( node->left , key );
else // key > node->key
return contain( node->right , key );
}
// 在以node为根的AVL树中查找key所对应的value, 递归算法
// 若value不存在, 则返回NULL
Value* search(Node* node, Key key){
if( node == NULL )
return NULL;
if( key == node->key )
return &(node->value);
else if( key < node->key )
return search( node->left , key );
else // key > node->key
return search( node->right, key );
}
// 对以node为根的AVL树进行前序遍历, 递归算法
void preOrder(Node* node){
if( node != NULL ){
cout<<node->key<<endl;
preOrder(node->left);
preOrder(node->right);
}
}
// 对以node为根的AVL树进行中序遍历, 递归算法
void inOrder(Node* node){
if( node != NULL ){
inOrder(node->left);
cout<<node->key<<endl;
inOrder(node->right);
}
}
// 对以node为根的AVL树进行后序遍历, 递归算法
void postOrder(Node* node){
if( node != NULL ){
postOrder(node->left);
postOrder(node->right);
cout<<node->key<<endl;
}
}
// 释放以node为根的AVL树的所有节点
// 采用后续遍历的递归算法
void destroy(Node* node){
if( node != NULL ){
destroy( node->left );
destroy( node->right );
delete node;
count --;
}
}
// 返回以node为根的AVL树的最小键值所在的节点, 递归算法
Node* minimum(Node* node){
if( node->left == NULL )
return node;
return minimum(node->left);
}
// 返回以node为根的AVL树的最大键值所在的节点, 递归算法
Node* maximum(Node* node){
if( node->right == NULL )
return node;
return maximum(node->right);
}
// 删除掉以node为根的AVL树中键值为key的节点, 递归算法
// 返回删除节点后新的AVL树的根
Node* remove(Node* node, Key key){
Node* retNode;
if( node == NULL )
return NULL;
if( key < node->key ){
node->left = remove( node->left , key );
retNode = node;
}
else if( key > node->key ){
node->right = remove( node->right, key );
retNode = node;
}
else{ // key == node->key
if( node->left == NULL ){
Node *rightNode = node->right;
delete node;
count --;
retNode = rightNode;
}
else if( node->right == NULL ){
Node *leftNode = node->left;
delete node;
count--;
retNOde = leftNode;
}
else{// node->left != NULL && node->right != NULL
Node *successor = new Node(minimum(node->right));
count++;
successor->right = remove(node->right,successor->key);
successor->left = node->left;
delete node;
count--;
retNode = successor;
}
}
if (retNode == NULL)
return NULL;
retNode->height = 1 + max(getHeight(retNode->left), getHeight(retNode->right));
//
int balanceFactor = getBalanceFactor(retNode);
if (balaceFactor >1 && getBalanceFactor(retNode->left) >= 0)
retNode = rightRotate(retNode);
if (balaceFactor <-1 && getBalanceFactor(retNode->right) <= 0)
retNode = leftRotate(retNode);
if (balaceFactor >1 && getBalanceFactor(retNode->left) < 0){
retNode->left = leftRotate(retNode->left);
return rightRotate(retNode);
}
if (balaceFactor < -1 && getBalanceFactor(retNode->right) > 0){
retNode->right = rightRotate(retNode->right);
return leftRotate(retNode);
}
return retNode;
}
};