包含了AVL树的单旋转和双旋转的算法,以及AVL树的递归插入和非递归插入算法。单旋转也叫“一”字形旋转,又可分为左-左型旋转和右-右型旋转;双旋转也叫“之”字形旋转,又可分为左-右型旋转和右-左型旋转。
#include<iostream>
#include<stack>
using namespace std;
class AVLNode{
public:
int element;
AVLNode* left;
AVLNode* right;
int height;
AVLNode(int x, AVLNode*l = NULL, AVLNode*r = NULL, int h = 0) :element(x), left(l), right(r), height(h){}
};
int getHeight(AVLNode* t){
if (t == NULL){
return -1;
}
else{
int leftHeight = getHeight(t->left);
int rightHeight = getHeight(t->right);
return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
}
}
//左-左型旋转
/*
K2-> O K2-> O K1-> O
/ /| / \
K1-> O ----> K1-> O | ----> O O <-K2
/ \ / | /
O O O O O
*/
void rotateWithLeftChild(AVLNode* k2){
AVLNode*k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2 = k1;
}
//右-右型旋转
/*
K2-> O K2-> O K1-> O
\ |\ / \
K1-> O ----> | O <-K1 ----> K2-> O O
/ \ | \ \
O O O O O
*/
void rotateWithRightChild(AVLNode* k2){
AVLNode* k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
k2 = k1;
}
//左-右型双旋转
/*
k3-> O k3-> O k3-> O
/ \ / \ / \
k3->left-> O O O O O O
/ \ ---> / \ ----> / \ / \
O O K3.left->O O O O O O
/ \ / \
O O O O
*/
void doubleWithLeftChild(AVLNode* k3){
//先对k3的左子树进行右-右型单旋转
rotateWithRightChild(k3->left);
//再对k3进行左-左型单旋转
rotateWithLeftChild(k3);
}
//右-左型双旋转
/*
O <-K3 O <-K3 O <-K3
/ \ / \ / \
O O <-K3.right O O O O
/ \ -----> / \ -----> / \ / \
O O O O <-K3.right O O O O
/ \ / \
O O O O
*/
void doubleWithRightChild(AVLNode* k3){
//先对右子树进行左-左型单旋转
rotateWithLeftChild(k3->right);
//再对K3进行右-右型单旋转
rotateWithRightChild(k3);
}
//递归实现AVL树插入
void insert(const int &x, AVLNode* t){
if (t == NULL){
t = new AVLNode(x);
}
else if (x < t->element){
insert(x, t->left);
//如果不平衡就调整
//在左子树插入,用左高度-右高度
if (getHeight(t->left) - getHeight(t->right) == 2){
//如果是左-左型
if (x < t->left->element){
//进行单旋转
rotateWithLeftChild(t);
}
//如果是左-右型
else{
//进行双旋转
doubleWithLeftChild(t);
}
}
}
else if (t->element < x){
insert(x, t->right);
//如果不平衡就调整
//在右子树插入,用右高度-左高度
if (getHeight(t->right) - getHeight(t->left) == 2){
//如果是右-右型
if (x > t->right->element){
//进行单旋转
rotateWithRightChild(t);
}
//如果是右-左型
else{
//进行双调整
doubleWithRightChild(t);
}
}
}
else{
;
}
}
//非递归实现AVL树插入
//利用栈来保存每个节点的父节点,实现自底向上检索插入路径上的每个节点是否平衡
void insert_2(const int & x, AVLNode*tree){
AVLNode * t = tree;
std::stack<AVLNode*> route;
//插入
while (true){
if (!t){
t = new AVLNode(x);
route.push(t);
break;
}
else if (t->element < x){
route.push(t);
t = t->right;
continue;
}
else if (x < t->element){
route.push(t);
t = t->left;
continue;
}
else{ ; }
}
AVLNode *father, *son;
//调整
while (true){
son = route.top();
route.pop();
//当栈里只有一个节点时,说明自底向上回溯只剩根节点,则退出循环
if (route.empty()){
break;
}
father = route.top();
route.pop();
//son节点在father节点的左边
if (son->element < father->element){
//如果不平衡
if (getHeight(father->left) - getHeight(father->right) == 2){
/*
判断插入的x在son节点的左还是右
实质是判断“一”字形还是“之”字形
*/
if (son->element < x){ //x在son节点的右边
//说明是“之”字形
doubleWithLeftChild(father);
}
else if(x < son->element){ //x在son节点的左边
//说明是“一”字形
rotateWithLeftChild(father);
}
else{ //son节点是x
//不可能产生不平衡
return;
}
}
route.push(father);
}
//son节点在father节点的右边
else{
//如果不平衡
if (getHeight(father->right) - getHeight(father->left) == 2){
if (son->element < x){
//"一"字形
rotateWithRightChild(father);
}
else{
doubleWithRightChild(father);
}
}
route.push(father);
}
}
}