二叉平衡树(AVL树),是带有平衡条件的二叉树查找树,这个平衡条件必须要容易保持,且必须保证树的深度是O(logN).。这里的平衡条件是左右子树高度差最多差1的二叉查找树。如果插入一个节点后破坏了平衡条件,那么就要做一些操作去恢复AVL树, 这里的操作一般称为旋转。
第一种情况是插入的节点在外面,即(左-左或右-右)、另一种是节点插在里面,即(左-右或右-左), 对于第一种情况我们采用单旋转,第二种采用双旋转,如下图:
代码实现
头文件 avl.h
#ifndef AVL_H_
#define AVL_H_
struct Node;
typedef int ElementType;
typedef struct Node *ptrToNode;
typedef struct Node *AVLTree;
// 插入节点
ptrToNode insert(AVLTree T,ElementType e);
// 左单旋转
ptrToNode singleRoateWithLeft(ptrToNode ptr);
// 左右双旋转
ptrToNode doubleRoateWithLeftRight(ptrToNode ptr);
// 右单旋转
ptrToNode singleRoateWithRight(ptrToNode ptr);
// 右左双旋转
ptrToNode doubleRoateWithRightLeft(ptrToNode ptr);
// 中序遍历
void midPrint(AVLTree T);
// 返回节点的高度
int height(AVLTree T);
// 返回最大值
int max(int a, int b);
// 销毁树
void destory(AVLTree &T);
#endif /* AVL_H_ */
具体实现 avl.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "avl.h"
struct Node {
ElementType data;
ptrToNode left;
ptrToNode right;
int height;
};
/**
* 插入数据,构建二叉树
*/
ptrToNode insert(AVLTree T, ElementType e) {
if (T == NULL) {
T = (ptrToNode) malloc(sizeof(struct Node));
T->data = e;
T->height = 0;
T->left = NULL;
T->right = NULL;
} else {
if (e < T->data) {
T->left = insert(T->left, e);
if (height(T->left) - height(T->right) >= 2) {
if (e < T->left->data) // 左-左
T = singleRoateWithLeft(T);
else// 左-右
T = doubleRoateWithLeftRight(T);
}
} else {
T->right = insert(T->right, e);
if (height(T->right) - height(T->left) >= 2) {
if (e > T->right->data) // 右-右
T = singleRoateWithRight(T);
else // 右-左
T = doubleRoateWithRightLeft(T);
}
}
}
//更新节点高度
T->height = max(height(T->left), height(T->right)) + 1;
return T;
}
/**
* 左单旋转
*/
ptrToNode singleRoateWithLeft(ptrToNode ptr) {
ptrToNode k1, k2;
k2 = ptr;
k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max(height(k2->left), height(k2->right)) + 1;
k1->height = max(height(k1->left), height(k1->right)) + 1;
return k1;
}
/**
* 又单旋转
*/
ptrToNode singleRoateWithRight(ptrToNode ptr) {
ptrToNode k1, k2;
k2 = ptr;
k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
k2->height = max(height(k2->left), height(k2->right)) + 1;
k1->height = max(height(k1->left), height(k1->right)) + 1;
return k1;
}
/**
* 左右双旋转
*/
ptrToNode doubleRoateWithLeftRight(ptrToNode ptr) {
ptr->left = singleRoateWithRight(ptr->left);
return singleRoateWithLeft(ptr);
}
/**
* 右左双旋转
*/
ptrToNode doubleRoateWithRightLeft(ptrToNode ptr) {
ptr->right = singleRoateWithLeft(ptr->right);
return singleRoateWithRight(ptr);
}
/**
* 中序遍历
*/
void midPrint(AVLTree T) {
if (T == NULL)
return;
midPrint(T->left);
//输出节点和高度
printf("%d %d\n", T->data, T->height);
midPrint(T->right);
}
/**
* 返回节点高度
*/
int height(AVLTree T) {
if (T == NULL)
return -1;
else
return T->height;
}
/**
* 返回最大值
*/
int max(int a, int b) {
return a > b ? a : b;
}
/**
* 销毁二叉树
*/
void destory(AVLTree &T) {
if(T ==NULL)
return;
free(T);
T =NULL;
}
测试
#include <stdio.h>
#include "avl.h"
int main() {
AVLTree T = NULL;
T = insert(T, 6);
T = insert(T, 5);
T = insert(T, 4);
T = insert(T, 3);
T = insert(T, 2);
T = insert(T, 1);
midPrint(T);
destory(T);
return 0;
}