AVL树
一颗AVL树或者空树,它具有二叉搜索树的性质,它的左子树和右子树都是AVL树,且左子树和右子树的高度只差绝对值不超过1
当插入一个值后,左右子树高度差之不小于1,那么就要做平衡处理。
有一个左平衡,一个右平衡,一个左旋转,一个右旋转,当插入后balance的绝对值大于一时,就需要就需要旋转,并且重新改变balance的值,
1.如果插入的数据在一条直线上,就只旋转一次,是在左边就进行左旋转,在右边,就进行右旋转,旋转后把第二个节点提上去,父子节点分别挂在两边。之后再分别把balance改变
2.如果插入的是一条折线,就需要进行两次旋转,一次右旋转,再一次左旋转,如下图。
#include<stddef.h>
#include<stdio.h>
#include<iostream>
#include<assert.h>
using namespace std;
typedef int KeyType;
typedef struct AVLNode
{
KeyType key;
struct AVLNode* leftchild;
struct AVLNode* parent;
struct AVLNode* rightchild;
int balance;
}AVLNode,*AVLTree;
AVLNode* Buynode(KeyType kx)
{
AVLNode* s = (AVLNode*)malloc(sizeof(AVLNode));
if (s == nullptr)exit(1);
memset(s, 0, sizeof(AVLNode));
s->key = kx;
s->balance = 0;
return s;
}
AVLNode* MakeRoot(KeyType kx)
{
AVLNode* root = Buynode(kx);
return root;
}
void RotateLeft(AVLTree& tree, AVLNode* ptr)
{
AVLNode* newroot = ptr->rightchild;
newroot->parent = ptr->parent;
ptr->rightchild = newroot->leftchild;
if (newroot->leftchild != nullptr)
{
newroot->leftchild->parent = ptr;
}
newroot->leftchild = ptr;
if (ptr == tree)
{
tree = newroot;
}
else
{
if (ptr->parent->leftchild == ptr)
{
ptr->parent->leftchild = newroot;
}
else
{
ptr->parent->rightchild = newroot;
}
}
ptr->parent = newroot;
}
void RotateRight(AVLTree& tree, AVLNode* ptr)
{
AVLNode* newroot = ptr->leftchild;
newroot->parent = ptr->parent;
ptr->leftchild = newroot->rightchild;
if (newroot->rightchild != nullptr)
{
newroot->rightchild->parent = ptr;
}
newroot->rightchild = ptr;
if (ptr == tree)
{
tree = newroot;
}
else
{
if (ptr->parent->leftchild == ptr)
{
ptr->parent->leftchild = newroot;
}
else
{
ptr->parent->rightchild = newroot;
}
}
ptr->parent = newroot;
}
void RightBalance(AVLTree& tree, AVLNode* ptr)
{
AVLNode* rightsub = ptr->rightchild, * leftsub = nullptr;
switch (rightsub->balance)
{
case 0:cout << "right balance" << endl;break;
case 1:
ptr->balance = 0;
rightsub->balance = 0;
RotateLeft(tree, ptr);
break;
case -1:
leftsub = rightsub->leftchild;
switch (leftsub->balance)
{
case 0:
ptr->balance = 0;
rightsub->balance = 0;
break;
case 1:
ptr->balance = -1;
rightsub->balance = 0;
break;
case -1:
ptr->balance = 0;
rightsub->balance = 1;
break;
}
leftsub->balance = 0;
RotateRight(tree, rightsub);
RotateLeft(tree, ptr);
break;
}
}
void LeftBalance(AVLTree& tree, AVLNode* ptr)
{
AVLNode* leftsub = ptr->leftchild, * rightsub = nullptr;
switch (leftsub->balance)
{
case 0: cout << "left balance " << endl; break;
case -1:
ptr->balance = 0;
leftsub->balance = 0;
RotateRight(tree, ptr);
break;
case 1:
rightsub = leftsub->rightchild;
switch (rightsub->balance)
{
case -1:
leftsub->balance = 0;
ptr->balance = 1;
break;
case 1:
leftsub->balance = -1;
ptr->balance = 0;
break;
case 0:
leftsub->balance = 0;
ptr->balance = 0;
break;
}
rightsub->balance = 0;
RotateLeft(tree, leftsub);
RotateRight(tree, ptr);
break;
}
}
void PassBalance(AVLTree& tree, AVLNode* p)
{
AVLNode* pa = p->parent;
bool tall = true;
for (; pa != nullptr && tall;)
{
if (pa->leftchild == p)
{
switch (pa->balance)
{
case 0: pa->balance = -1; break;
case 1: pa->balance = 0;
tall = false;
break;
case -1:
LeftBalance(tree, pa);
tall = false;
break;
}
}
else // p -->pa->rightchild
{
switch (pa->balance)
{
case 0: pa->balance = 1; break;
case -1: pa->balance = 0;
tall = false;
break;
case 1:
RightBalance(tree, pa);
tall = false;
break;
}
}
p = pa;
pa = p->parent;
}
}
bool Insert(AVLTree& tree, KeyType kx)
{
if (tree == nullptr)
{
tree = MakeRoot(kx);
return true;
}
AVLNode* pa = nullptr;
AVLNode* p = tree;
while (p != nullptr && p->key != kx)
{
pa = p;
p = kx < p->key ? p->leftchild : p->rightchild;
}
if ( p != nullptr&& p->key == kx)return false;
p = Buynode(kx);
p->parent = pa;
if (kx < pa->key)
{
pa->leftchild = p;
}
else
{
pa->rightchild = p;
}
PassBalance(tree, p);
return true;
}
void InOrder(AVLNode* ptr)
{
if (ptr != NULL)
{
InOrder(ptr->leftchild);
cout << ptr->key << " " << ptr->balance << endl;
InOrder(ptr->rightchild);
}
}
int main()
{
int ar[] = { 16,3,7,11,9,26,18,14,15 };
AVLTree root = nullptr;
for (auto& x : ar)
{
cout << Insert(root, x) << endl;
}
InOrder(root);
return 0;
}