1、我们首先要计算节点的高度和平衡因子。
// 计算每个节点的高度
int getHeight(Node<K, V> * node){
if (node == NULL) return 0;
return node->height;
}
// 获得节点node的平衡因子
int getBalanceFactor(Node<K, V> * node){
if (node == NULL)
return 0;
return getHeight(node->left) - getHeight(node->right);
}
// 判断以Node为根的二叉树是否是一棵平衡二叉树,递归算法
bool isBalanced(Node<K,V> *node){
if (node == NULL)
return true;
int balanceFactor = getBalanceFactor(node);
if (abs(balanceFactor) > 1)
return false;
return isBalanced(node->left) && isBalanced(node->right);
}
// 判断该二叉树是否是一棵二分搜索树
bool isBST(){
vector<K> keys;
inOrder(root, keys);
for (int i = 1; i < keys.size(); i++)
if (keys[i - 1]>keys[i])
return false;
return true;
}
//中序便利
void inOrder(Node<K,V> * node, vector<K> keys){
if (node == NULL)
return;
inOrder(node->left, keys);
keys.push_back(node->key);
inOrder(node->right, keys);
}
2、右旋转的操作
// 对节点y进行向右旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// x T4 向右旋转 (y) z y
// / \ - - - - - - - -> / \ / \
// z T3 T1 T2 T3 T4
// / \
// T1 T2
Node<K,V> * rightRotate(Node<K,V> * y) {
Node<K, V> * x = y->left;
Node<K, V> * T3 = x->right;
x->right = y;
y->right = T3;
// 更新height
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
3、左旋转的过程。
// 对节点y进行向左旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// T1 x 向左旋转 (y) y z
// / \ - - - - - - - -> / \ / \
// T2 z T1 T2 T3 T4
// / \
// T3 T4
Node<K, V> * leftRotate(Node<K, V> *y) {
Node<K, V> * x = y->right;
Node<K, V> * T2 = x->left;
// 向左旋转过程
x->left = y;
y->right = T2;
// 更新height
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;//顺序不能够改变
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
4、LL和RR 和 LR 和RL 过程。
//1、添加结点就是一个不断的回溯的过程。
node->height = 1 + max(getHeight(node->left), getHeight(node->right)); //计算结点的高度
int BalanceFactor = getBalanceFactor(node);
//LL
if (BalanceFactor > 1 && getBalanceFactor(node->left) >= 0){
return rightRotate(node);
}
//RR
if (BalanceFactor <-1 && getBalanceFactor(node->right) <= 0){
return leftRotate(node);
}
//LR
if (BalanceFactor > 1 && getBalanceFactor(node->left) < 0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
//RL
if (BalanceFactor <-1 && getBalanceFactor(node->right) >0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
整个代码的实现
#ifndef AVLMAP2
#define AVLMAP2
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cassert>
using namespace std;
template<class K, class V>
struct Node {
K key;
V value;
Node * left;
Node * right;
int height;
Node(K k, V v) : key(k), value(v), left(NULL), right(NULL), height(1){}
};
template<class K, class V>
class AVLTree2{
private:
Node<K, V> * root;
int size;
// 向以node为根的二分搜索树中插入元素e,递归算法
Node<K, V> * add(Node<K, V> * node, K k, V v){
if (node == NULL){
size++;
return new Node<K, V>(k, v);
}
if (k < node->key){ //表示的是 该值比较小,并且它的左孩子为NULL
node->left = add(node->left, k, v); //去节点的左边找。
}
else if (k > node->key){ //表示的是该值比较大,并且它的右孩子为NULL
node->right = add(node->right, k, v);//去节点的右边找。
}
else{
node->value = v;
}
//1、添加结点就是一个不断的回溯的过程。
node->height = 1 + max(getHeight(node->left), getHeight(node->right)); //计算结点的高度
int BalanceFactor = getBalanceFactor(node);
//LL
if (BalanceFactor > 1 && getBalanceFactor(node->left) >= 0){
return rightRotate(node);
}
//RR
if (BalanceFactor <-1 && getBalanceFactor(node->right) <= 0){
return leftRotate(node);
}
//LR
if (BalanceFactor > 1 && getBalanceFactor(node->left) < 0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
//RL
if (BalanceFactor <-1 && getBalanceFactor(node->right) >0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
int getHeight(Node<K, V> * node){
if (node == NULL) return 0;
return node->height;
}
// 获得节点node的平衡因子
int getBalanceFactor(Node<K, V> * node){
if (node == NULL)
return 0;
return getHeight(node->left) - getHeight(node->right);
}
// 中序遍历以node为根的二分搜索树, 递归算法
void inOrder(Node<K, V> * node){
if (node == NULL)
return;
inOrder(node->left);
cout << node->key << " ";
inOrder(node->right);
}
// 返回以node为根节点的二分搜索树中,key所在的节点
Node<K, V> * getNode(Node<K, V> * node, K key){
if (node == NULL)
return NULL;
if (key == node->key)
return node;
else if (key < node->key)
return getNode(node->left, key);
else // if(key.compareTo(node.key) > 0)
return getNode(node->right, key);
}
// 对节点y进行向右旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// x T4 向右旋转 (y) z y
// / \ - - - - - - - -> / \ / \
// z T3 T1 T2 T3 T4
// / \
// T1 T2
Node<K,V> * rightRotate(Node<K,V> * y) {
Node<K, V> * x = y->left;
Node<K, V> * T3 = x->right;
x->right = y;
y->right = T3;
// 更新height
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
// 对节点y进行向左旋转操作,返回旋转后新的根节点x
// y x
// / \ / \
// T1 x 向左旋转 (y) y z
// / \ - - - - - - - -> / \ / \
// T2 z T1 T2 T3 T4
// / \
// T3 T4
Node<K, V> * leftRotate(Node<K, V> *y) {
Node<K, V> * x = y->right;
Node<K, V> * T2 = x->left;
// 向左旋转过程
x->left = y;
y->right = T2;
// 更新height
y->height = max(getHeight(y->left), getHeight(y->right)) + 1;//顺序不能够改变
x->height = max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
public:
AVLTree2(){
root = NULL;
size = 0;
}
void add(K key, V value){
root = add(root, key, value);
}
V remove(K key){
Node<K, V> * node = getNode(root, key);
if (node != NULL){ //如果存在
root = remove(root, key);
return node->value;
}
return NULL;
}
void inOrder(){
inOrder(root);
}
// 删除掉以node为根的二分搜索树中值为e的节点, 递归算法
// 返回删除节点后新的二分搜索树的根
Node<K, V> * remove(Node<K, V> * node, K e){
if (node == NULL)
return NULL;
Node<K, V> * res;
if (e<node->key){
node->left = remove(node->left, e);
res = node;
//return node;
}
else if (e>node->key){
node->right = remove(node->right, e);
res = node;
}
else{ // e.compareTo(node.e) == 0
// 待删除节点左子树为空的情况
if (node->left == NULL){
Node<K, V> * rightNode = node->right;
node->right = NULL;
size--;
res = rightNode;
// return rightNode;
}
// 待删除节点右子树为空的情况
else if (node->right == NULL){
Node<K, V> * leftNode = node->left;
node->left = NULL;
size--;
res= leftNode;
}
else{
// 待删除节点左右子树均不为空的情况
// 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
// 用这个节点顶替待删除节点的位置
Node<K, V> * successor = minimum(node->right);
successor->right = remove(node->right,node->key);
successor->left = node->left;
node->left = node->right = NULL;
res = successor;
// return successor;
}
}
if (res == NULL) return NULL;
//1、添加结点就是一个不断的回溯的过程。
res->height = 1 + max(getHeight(res->left), getHeight(res->right)); //计算结点的高度
int BalanceFactor = getBalanceFactor(res);
//LL
if (BalanceFactor > 1 && getBalanceFactor(res->left) >= 0){
return rightRotate(res);
}
//RR
if (BalanceFactor <-1 && getBalanceFactor(res->right) <= 0){
return leftRotate(res);
}
//LR
if (BalanceFactor > 1 && getBalanceFactor(res->left) < 0){
res->left = leftRotate(res->left);
return rightRotate(res);
}
//RL
if (BalanceFactor <-1 && getBalanceFactor(res->right) >0){
res->right = rightRotate(res->right);
return leftRotate(res);
}
return res;
}
bool contains(K key){
Node<K, V> * node = getNode(root, key);
if (node == NULL) { return false; }
return true;
}
V get(K key){
Node<K, V> * node = getNode(root, key);
return node == NULL ? NULL : node->value;
}
void set(K key, V newValue){
Node<K, V> * node = getNode(root, key);
if (node == NULL) cout << "不存在该值" << endl;
else{
node->value = newValue;
}
}
int getSize(){ return size; }
bool isEmpty(){ return size == 0; }
// 返回以node为根的二分搜索树的最小值所在的节点
Node<K, V> * minimum(Node<K, V> * node){
if (node->left == NULL)
return node;
return minimum(node->left);
}
// 删除掉以node为根的二分搜索树中的最小节点
// 返回删除节点后新的二分搜索树的根
/*
Node<K, V> * removeMin(Node<K, V> * node){
if (node->left == NULL){
Node<K, V> * rightNode = node->right;
node->right = NULL;
size--;
return rightNode;
}
node->left = removeMin(node->left);
return node;
}
*/
// 判断该二叉树是否是一棵平衡二叉树
bool isBalanced(){
return isBalanced(root);
}
// 判断以Node为根的二叉树是否是一棵平衡二叉树,递归算法
bool isBalanced(Node<K,V> *node){
if (node == NULL)
return true;
int balanceFactor = getBalanceFactor(node);
if (abs(balanceFactor) > 1)
return false;
return isBalanced(node->left) && isBalanced(node->right);
}
// 判断该二叉树是否是一棵二分搜索树
bool isBST(){
vector<K> keys;
inOrder(root, keys);
for (int i = 1; i < keys.size(); i++)
if (keys[i - 1]>keys[i])
return false;
return true;
}
void inOrder(Node<K,V> * node, vector<K> keys){
if (node == NULL)
return;
inOrder(node->left, keys);
keys.push_back(node->key);
inOrder(node->right, keys);
}
};
#endif;