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