AVL树的插入很简单,根据BST树的特性插入之后在回溯的过程中调整即可
AVL树的删除也不是很难,一共有三种情况
第一种是左子树为空(右子树为不为空无所谓)
第二种是右子树为空(此时左子树不为空)
这两种直接用另一半子树覆盖当前节点然后删除再回溯调整树即可
第三种是左右子数都不为空
这个情况首先找到要删除的节点,然后找到比该节点大的节点中最小的一个节点(右子树中最左边的节点),或者比该节点小的节点中最大的一个节点(左子树中最右边的节点),然后交换这两个节点后再删除原节点(此时就变成了上面两种情况的其中一种),之后回溯的时候调整树
至于为什么要找这两个节点,是因为要保证删除之后还是一颗BST树
AVLTree.h
#pragma once
typedef int ElemType;
struct AVLTreeNode {
ElemType val;
int height;
AVLTreeNode * left;
AVLTreeNode * right;
AVLTreeNode(const ElemType & _val = ElemType(), const int & _height = int(),
AVLTreeNode * _left = nullptr, AVLTreeNode * _right = nullptr)
: val(_val), height(_height), left(_left), right(_right) {}
};
class AVLTree {
public:
AVLTree(void) { root = nullptr; }
~AVLTree(void) { clear(root); }
void insert(const ElemType &);
void erase(const ElemType &);
inline void inOrder(void) { inOrder(root); }
private:
inline AVLTreeNode * rotateRR(AVLTreeNode *);
inline AVLTreeNode * rotateRL(AVLTreeNode *);
inline AVLTreeNode * rotateLR(AVLTreeNode *);
inline AVLTreeNode * rotateLL(AVLTreeNode *);
AVLTreeNode * insert(AVLTreeNode *, const ElemType &);
AVLTreeNode * erase(AVLTreeNode *, const ElemType &);
inline int getHeight(AVLTreeNode *);
inline void clear(AVLTreeNode *);
inline void inOrder(AVLTreeNode *);
private:
AVLTreeNode * root;
};
AVLTree.cpp
包含algorithm头文件是因为要用到max函数(也可以自己写)
#include <algorithm>
#include "AVLTree.h"
void AVLTree::insert(const ElemType & val) {
root = insert(root, val);
}
void AVLTree::erase(const ElemType & val) {
root = erase(root, val);
}
inline AVLTreeNode * AVLTree::rotateRR(AVLTreeNode * node) {
AVLTreeNode * child = node->left;
AVLTreeNode * rGrandchild = child->right;
child->right = node;
node->left = rGrandchild;
node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
child->height = 1 + std::max(getHeight(node), getHeight(child->left));
return child;
}
inline AVLTreeNode * AVLTree::rotateRL(AVLTreeNode * node) {
node->right = rotateRR(node->right);
return rotateLL(node);
}
inline AVLTreeNode * AVLTree::rotateLR(AVLTreeNode * node) {
node->left = rotateLL(node->left);
return rotateRR(node);
}
inline AVLTreeNode * AVLTree::rotateLL(AVLTreeNode * node) {
AVLTreeNode * child = node->right;
AVLTreeNode * lGrandchild = child->left;
child->left = node;
node->right = lGrandchild;
node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
child->height = 1 + std::max(getHeight(node), getHeight(child->right));
return child;
}
AVLTreeNode * AVLTree::insert(AVLTreeNode * node, const ElemType & val) {
if (nullptr == node) {
node = new AVLTreeNode(val);
}
else if (node->val < val) {
node->right = insert(node->right, val);
}
else {
node->left = insert(node->left, val);
}
node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
if (getHeight(node->left) - getHeight(node->right) >= 2) {
if (node->left->val < val) {
node = rotateLR(node);
}
else {
node = rotateRR(node);
}
}
else if (getHeight(node->right) - getHeight(node->left) >= 2) {
if (node->right->val < val) {
node = rotateLL(node);
}
else {
node = rotateRL(node);
}
}
return node;
}
AVLTreeNode * AVLTree::erase(AVLTreeNode * node, const ElemType & val) {
if (nullptr == node) {
return nullptr;
}
if (val == node->val) {
if (nullptr == node->left) {
AVLTreeNode * tmp = node;
node = node->right;
delete tmp;
return node;
}
else if (nullptr == node->right) {
AVLTreeNode * tmp = node;
node = node->left;
delete tmp;
return node;
}
else {
AVLTreeNode * tmp = node->right;
while (tmp->left) {
tmp = tmp->left;
}
node->val = tmp->val;
node->right = erase(node->right, tmp->val);
}
}
else if (node->val < val) {
node->right = erase(node->right, val);
}
else {
node->left = erase(node->left, val);
}
node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
if (getHeight(node->left) - getHeight(node->right) >= 2) {
if (getHeight(node->left->left) > getHeight(node->left->right)) {
node = rotateLR(node);
}
else {
node = rotateRR(node);
}
}
else if (getHeight(node->right) - getHeight(node->left) >= 2) {
if (getHeight(node->right->right) > getHeight(node->right->left)) {
node = rotateLL(node);
}
else {
node = rotateRL(node);
}
}
return node;
}
inline int AVLTree::getHeight(AVLTreeNode * node) {
return nullptr == node ? -1 : node->height;
}
inline void AVLTree::inOrder(AVLTreeNode * node) {
if (nullptr == node) {
return;
}
inOrder(node->left);
// output
inOrder(node->right);
}
inline void AVLTree::clear(AVLTreeNode * node) {
if (nullptr != node) {
clear(node->left);
clear(node->right);
delete node;
node = nullptr;
}
}