AVL树
- 是一棵二叉树,任意节点至多2个子节点;
- 是一棵二叉排序树,任一节点的左子节点的数据都比自身数据小,右子节点的数据都比自身数据大;
- 任意节点的子树高度之差不超过1。
AVL树 “插入删除三步走”
- 找到要插入、删除的位置,进行插入或删除操作;
- 检查树的平衡性,找到失衡节点(递归);
- 辨别失衡节点的形态,进行相应的高度调整操作。
Q1:怎么找到插入的位置?
A: 根据二叉排序树的性质。
- 如果树的根节点为空,则用新节点替换根节点,高度为 0;
- 如果要插入的数据小于根节点的数据,则在树的左子树中查找插入位置;
- 如果要插入的数据大于根节点的数据,则在树的右子树中查找插入位置。
AVL树节点的定义
#include <stdio.h>
#include <stdlib.h>
typdef int DataType;
/**
* @data: 数据域
* @left: 指向左子节点的指针
* @right: 指向右子节点的指针
* @height: 树的高度(子树高者高度+1)
typedef struct avl_node {
DataType data;
struct avl_node* left;
struct avl_node* right;
int height;
} AVLNode;
查找操作(非递归)
AVLNode* Find(AVLNode* root, DataType data) {
if(root == NULL) {
return NULL;
}
while(1) {
if(data == root->data)
return root;
if(data < root->data && root->left != NULL) {
root = root->left;
else if(data > root->data && root->right != NULL) {
root = root->right;
else
return NULL;
}
}
计算高度
int HEIGHT(AVLNode* root) {
if(root == NULL) {
return 0;
}
else if(root->left == NULL && root->right == NULL) {
return 1;
}
else {
return HEIGHT(root->left) > HEIGHT(root->right) ? root->left->height+1 : root->right->height+1;
}
}
前序、中序、后序遍历
void PreOrderTraverse(AVLNode* root) {
if(root != NULL) {
printf("data=%d, height=%d\n", root->data, root->height);
PreOrderTraverse(root->left);
PreOrderTraverse(root->right);
}
}
void InOrderTraverse(AVLNode* root) {
if(root != NULL) {
InOrderTraverse(root->left);
printf("data=%d, height=%d\n", root->data, root->height);
InOrderTraverse(root->right);
}
}
void PostOrderTraverse(AVLNode* root) {
if(root != NULL) {
PostOrderTraverse(root->left);
PostOrderTraverse(root->right);
printf("data=%d, height=%d\n", root->data, root->height);
}
}
旋转
AVLNode* L(AVLNode* node) {
AVLNode* t1 = node->left->right;
AVLNode* t2 = node->left;
node->left->right = node;
node->left = t1;
node = t2;
node->right->height = HEIGHT(node->right);
node->height = HEIGHT(node);
return node;
}
AVLNode* R(AVLNode* node) {
AVLNode* t1 = node->right->left;
AVLNode* t2 = node->right;
node->right->left = node;
node->right = t1;
node = t2;
node->left->height = HEIGHT(node->left);
node->height = HEIGHT(node);
return node;
}
插入
AVLNode* Insert(AVLNode* root, DataType data) {
AVLNode* t1 = NULL;
AVLNode* t2 = NULL;
if(root == NULL) {
root = (AVLNode*)malloc(sizeof(struct AVLNode));
if(root == NULL) {
perror("malloc failed");
return NULL;
}
root->data = data;
root->left = NULL;
root->right = NULL:
root->height = 0;
}
else if(data < root->data) {
root->left = Insert(root->left, data);
if(HEIGHT(root->left) - HEIGHT(root->right) > 1 {
if(data < root->left->data) { // <=> HEIGHT(root->left->left > HEIGHT(root->left->right)
root = L(root);
} else {
root->left = R(root->left);
root = L(root);
}
}
}
else if(data > root->data) {
root->right = Insert(root->right, data);
root->height = HEIGHT(root);
if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
if(data > root->right->data) {
root = R(root);
} else {
root->right = L(root->right);
root = R(root);
}
}
}
return root;
}
删除
AVLNode* FindMax(AVLNode* root) {
if(root == NULL) {
perror("illegal call");
return NULL;
}
while(root->right != NULL)
root = root->right;
return root;
}
AVLNode* Delete(AVLNode* root, DataType data) {
AVLNode* temp = NULL;
if(root == NULL) {
perror("empty tree");
return NULL;
}
else if(data < root->data) {
root->left = Delete(root->left, data);
if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
if(HEIGHT(root->right->left) < HEIGHT(root->right->right)) {
root = R(root);
}
else {
root->right = L(root->right);
root = R(root);
}
}
else if(data > root->data) {
root->right = Delete(root->right, data);
if(HEIGHT(root->left) - HEIGHT(root->right) > 1 {
if(HEIGHT(root->left->left) > HEIGHT(root->left->right)) {
root = L(root);
}
else {
root->left = R(root->left);
root = L(root);
}
}
}
else {
if(root->left == NULL && root->right == NULL) {
free(root);
return NULL;
}
else if(root->left == NULL && root->right != NULL) {
temp = root->right;
free(root);
return temp;
}
else if(root->left != NULL && root->right == NULL) {
temp = root->left;
free(root);
return temp;
}
else {
temp = FindMax(root->left);
root->data = temp->data;
root->left = Delete(root->left, temp->data);
if(HEIGHT(root->left) - HEIGHT(root->right) < -1 {
if(HEIGHT(root->right->left) < HEIGHT(root->right->right)) {
root = R(root);
}
else {
root->right = L(root->right);
root = R(root);
}
}
}
}
}