对AVL平衡树的实现,主要在于实现对节点的插入和删除,方法是先用二叉查找树的插入和删除方法进行插入和删除,再对插入或者删除过的树进行维护,使之满足 AVL平衡树的性质。这里对二叉树的插入和删除以及 AVL平衡树的插入和删除都附带写了一下,本来尝写成迭代形式的。最后发现删除时需考虑的情况较多,写成迭代形式,代码凌乱且恶心。有点强迫症,还是写成递归,稍微清晰一点。具体的 AVL平衡树介绍在这里。
#include "stdio.h"
#include "stdlib.h"
struct node
{
int key;
int height;
node *left;
node *right;
node (int);
};
node ::node (int key)
{
this->key = key;
this->height = 1;
this->left = NULL;
this->right = NULL;
}
int getHeight (node *root)
{
return root == NULL ? 0 : root->height;
}
int max (int a, int b)
{
return a > b ? a : b;
}
node* rightRoate (node *root)
{
node *lchild = root->left;
root->left = lchild->right;
lchild->right = root;
root->height = max (getHeight (root->left), getHeight (root->right)) + 1;
lchild->height = max (getHeight (lchild->left), getHeight (lchild->right)) + 1;
return lchild;
}
node* leftRoate (node *root)
{
node *rchild = root->right;
root->right = rchild->left;
rchild->left = root;
root->height = max (getHeight (root->left), getHeight (root->right)) + 1;
rchild->height = max (getHeight (rchild->left), getHeight (rchild->right)) + 1;
return rchild;
}
node* previousOrNext (node *root)
{
if (root == NULL) {
return NULL;
}
// get the previous of root
node *ptr = root->left;
while (ptr != NULL && ptr->right != NULL) {
ptr = ptr->right;
}
// if root has a previous node
if (ptr != NULL) {
return ptr;
}
// get the next node of root
ptr = root->right;
while (ptr != NULL && ptr->left != NULL) {
ptr = ptr->left;
}
// if ptr is not NULL, then root has a next node
// if ptr is NULL, that's to say, the root is a left node
return ptr;
}
node* insert (node *root, int key)
{
if (root == NULL) {
return new node (key);
}
// if the key exist
if (key == root->key) {
return root;
}
// insert key in left subtree
if (key < root->key) {
root->left = insert (root->left, key);
// insert key in right subtree
} else {
root->right = insert (root->right, key);
}
return root;
}
node *remove (node *root, int key)
{
// the key do not exist
if (root == NULL) {
return NULL;
}
// if the key is in left subtree
if (key < root->key) {
root->left = remove (root->left, key);
return root;
}
// if the key is in right subtree
if (key > root->key) {
root->right = remove (root->right, key);
return root;
}
// if the key is in current node.
// get the previous or next of current node
node *adj = previousOrNext (root);
// if adj is NULL, that's to say, root is a leaf node
if (adj == NULL) {
delete root;
return NULL;
}
// replace the key of root with adj's
root->key = adj->key;
// if adj is a previous node
if (adj->key < key) {
root->left = remove (root->left, adj->key);
return root;
}
// if adj if a next node.
root->right = remove (root->right, adj->key);
return root;
}
node* avltree_insert (node *root, int key)
{
if (root == NULL) {
return new node (key);
}
// if the key exist
if (key == root->key) {
return root;
}
// insert key in left subtree
if (key < root->key) {
root->left = avltree_insert (root->left, key);
// insert key in right subtree
} else {
root->right = avltree_insert (root->right, key);
}
root->height = max (getHeight (root->left), getHeight (root->right)) + 1;
int balance_factor = getHeight (root->left) - getHeight (root->right);
switch (balance_factor) {
case 2:
// need to ajust the left subtree
// left left case
if (key < root->left->key) {
root = rightRoate (root);
// left right case
} else {
root->left = leftRoate (root->left);
root = rightRoate (root);
}
break;
case -2:
// need to adjust the right subtree
// right right case
if (key > root->right->key) {
root = leftRoate (root);
// right left case
} else {
root->right = rightRoate (root->right);
root = leftRoate (root);
}
break;
default:
break;
}
return root;
}
node* avltree_remove (node *root, int key)
{
// the key do not exist
if (root == NULL) {
return NULL;
}
if (key < root->key) {
// if the key is in left subtree
root->left = avltree_remove (root->left, key);
} else if (key > root->key) {
// if the key is in right subtree
root->right = avltree_remove (root->right, key);
} else {
// if the key is in current node.
// get the previous or next of current node
node *adj = previousOrNext (root);
// if adj is NULL, that's to say, root is a leaf node
if (adj == NULL) {
delete root;
return NULL;
}
// replace the key of root with adj's
root->key = adj->key;
if (adj->key < key) {
// if adj is a previous node
root->left = avltree_remove (root->left, adj->key);
} else {
// if adj if a next node.
root->right = avltree_remove (root->right, adj->key);
}
}
root->height = max (getHeight (root->left), getHeight (root->right)) + 1;
int balance_factor = getHeight (root->left) - getHeight (root->right);
switch (balance_factor) {
case 2:
// need to ajust the left subtree
// left left case
if (getHeight (root->left->left) >= getHeight (root->left->right)) {
root = rightRoate (root);
// left right case
} else {
root->left = leftRoate (root->left);
root = rightRoate (root);
}
break;
case -2:
// need to adjust the right subtree
// right right case
if (getHeight (root->right->right) >= getHeight (root->right->left)) {
root = leftRoate (root);
// right left case
} else {
root->right = rightRoate (root->right);
root = leftRoate (root);
}
break;
default:
break;
}
return root;
}
void travese (node *root)
{
if (root == NULL) {
return;
}
travese (root->left);
printf("%d ", root->key);
travese (root->right);
}
int main()
{
node *root;
int elem[100];
for (int e = 0; e < 80; e++) {
elem[e] = rand () % 100;
root = avltree_insert (root, elem[e]);
}
for (int e = 0; e < 80; e++) {
root = avltree_remove (root, elem[e]);
}
return 0;
}
####引用####
AVL Tree | Set 1 (Insertion)
AVL Tree | Set 1 (Deletion)