平衡查找二叉树适合静态查找多于动态操作的场景。由于平衡二叉树的维护成本较高,工程中一般不用平衡二叉树,而是用红黑树代替。
平衡二叉树的优缺点
优点
平衡二叉树的平衡因子为-1,0或1,相比二叉查找树,平衡二叉树的查找成功的平均时间复杂度更加稳定。
缺点
平衡查找二叉树在不理想情况下,经常需要维护平衡因子,维护平衡因子可能需要较长的响应时间,对于响应时间敏感的应用来说是不能满足需求的。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct AVLNode {
int data;
int bf;
struct AVLNode* lchild;
struct AVLNode* rchild;
}AVLNode, * AVL;
//左旋
void L_Rotate(AVL* T) {
if (*T == NULL) return;
AVL rc = (*T)->rchild;
(*T)->rchild = rc->lchild; //将*T的右孩子的左孩子作为*T的右孩子
rc->lchild = *T; //将*T作为*T的右孩子的左孩子
*T = rc;//用*T的左孩子取代*T
}
//右旋
void R_Rotate(AVL* T) {
if (*T == NULL) return;
AVL lc = (*T)->lchild;
(*T)->lchild = lc->rchild; //将*T的左孩子的右孩子作为*T的左孩子
lc->rchild = *T; //将*T作为*T左孩子的右孩子
*T = lc;//用*T的you孩子取代*T
}
// 搜索结点
AVL search(AVL T, int data) {
if (T == NULL) {
return NULL;
}
if (T->data = data) {
return T;
}
else if (data < T->data) {
return search(T->lchild, data);
}
else {
return search(T->rchild, data);
}
}
//左平衡处理
void LeftBalance(AVL* T, bool* taller) {
if (*T == NULL) return;
AVL lc = (*T)->lchild;
if ((*T)->bf == 1) { //LL型,进行一次右旋
(*T)->bf = lc->bf = 0;
R_Rotate(T);
}
else if ((*T)->bf == -1) {//LR型
//更新bf
AVL rc = (*T)->rchild;
switch (rc->bf) {
case -1:
(*T)->bf = 0;
lc->bf = 1;
case 0:
lc->bf = (*T)->bf = 0;
break;
case 1:
(*T)->bf = -1;
lc->bf = 0;
break;
}
rc->bf = 0; //*T的左孩子的右子树的根将替换*T,且bf为0
//先左旋
L_Rotate(&(*T)->lchild);
//再右旋
R_Rotate(T);
}
}
//右平衡处理
void RightBalance(AVL* T, bool* taller) {
AVL rc = (*T)->rchild;
if (rc->bf == -1) { // RR型
(*T)->bf = rc->bf = 0;
L_Rotate(T);
}
else if (rc->bf == 1) { //RL型
AVL lc = rc->lchild;
switch (lc->bf) {
case -1:
rc->bf = 0;
(*T)->bf = 1;
break;
case 0:
rc->bf = (*T)->bf = 0;
break;
case 1:
rc->bf = -1;
(*T)->bf = 0;
break;
}
lc->bf = 0; //*T的右孩子的左子树的根将替换*T,且bf为0
R_Rotate(&(*T)->rchild); //先右旋
L_Rotate(T);//再左旋
}
}
//插入结点
void insert(AVL* T, int data, bool* taller) {
if (*T == NULL) { //插入空树
AVL node = (AVL)malloc(sizeof(AVLNode));
if (node == NULL) exit(0);
node->data = data;
node->bf = 0;
node->lchild = node->rchild = NULL;
*T = node;
*taller = true; //树长高可能会导致不平衡
}
else if (data < (*T)->data) { //向左子树中插入
insert(&(*T)->lchild, data, taller);
if (*taller) {
switch ((*T)->bf) {
case -1:
(*T)->bf = 0;
*taller = false;
break;
case 0:
(*T)->bf = 1;
*taller = true;
break;
case 1:
LeftBalance(T, taller);
*taller = false;
break;
}
}
}
else if (data > (*T)->data) { //向右子树中插入
insert(&(*T)->rchild, data, taller);
if (*taller) {
switch ((*T)->bf) {
case -1:
RightBalance(T, taller);
*taller = false;
break;
case 0:
(*T)->bf = -1;
*taller = true;
break;
case 1:
(*T)->bf = 0;
*taller = false;
break;
}
}
}
else if (data == (*T)->data) {
*taller = false;
return;
}
}
// 中序遍历
void inOrder(AVL root) {
if (root == NULL) return;
inOrder(root->lchild);
printf("%d\n", root->data);
inOrder(root->rchild);
}
//测试
int main() {
int a[] = { 3,5,1,6,7,4,9 };
int n = sizeof(a) / sizeof(int);
AVL root = NULL;
bool taller = false;
for (int i = 0; i < n; i++) {
insert(&root, a[i], &taller);
}
inOrder(root);
return 0;
}