二叉平衡树概念
二叉平衡树首先是一棵二叉排序树
若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
左、右子树也分别为二叉排序树;
左右子树的高度差不超过一
二叉平衡树分类
跟据数据所处的位置分为:
LL 、RR、RL、LR
二叉平衡树类型判断
找到失衡的根节点root
找到导致失衡的节点node
判断node在root孩子的哪一侧 (左或右)
判断node在root的哪一侧 (左或右)
将两次判断连起来
LL型处理
取中间节点,将它的父亲作为自己的右孩子
自己的左孩子不变
自己的右孩子连到父亲的左孩子上
思考:
自己的右孩子肯定小于父亲节点,这是由二叉排序树的性质所决定的
伪代码:
node、root:
node->rchild = root
root->lchild = node->rchild
RR型处理
取中间节点,将它的父亲作为自己的左孩子
自己的右孩子不变
自己的左孩子连到父亲的右孩子上
思考:
自己的左孩子肯定大于父亲节点,这是由二叉排序树的性质所决定的
伪代码:
node、root:
node->lchild = root
root->rchild = node->lchild
LR型处理
(左即是小于,右即是大于)
思考:
node、root
L ====> root的孩子肯定小于root
R ====> node 肯定小于root,大于root的孩子
root->lchild < node < root
取node作为根节点
将node 的爷爷即root 作为自己的右节点
将node 的父亲作为自己的左节点
node的左孩子肯定小于node,大于node 的父亲,所以放到其父亲的右孩子上
node的右孩子肯定大于node 但小于node的爷爷,所以方法其爷爷的左孩子上
RL型处理
思考:
node、root
R ====> node 的爸爸大于node的爷爷
L ====> node肯定下于其爸爸,大于其爷爷
root < node < root->rchild
取node作为根节点
将node 的爷爷作为左节点
将node 的爸爸作为右节点
node的左孩子肯定小于node,大于node 的爷爷,所以放到其爷爷的右孩子上
node的右孩子肯定大于node 但小于node的爸爸,所以方法其爸爸的左孩子上
代码实现(更新中 。。。)
#include <stdio.h>
#include <stdlib.h>
typedef struct treenode
{
int data;
int height;
struct treenode *lchild;
struct treenode *rchild;
}TreeNode;
int getHeight(TreeNode *node){
return node ? node ->height : 0;
}
int max(int a, int b){
return a > b ? a:b;
}
void rrRotation(TreeNode *node, TreeNode **root){
TreeNode *temp = node ->rchild;
node ->rchild = temp ->lchild;
temp ->lchild = node;
node ->height = max(getHeight(node ->lchild), getHeight(node ->rchild)) + 1;
temp ->height = max(getHeight(temp ->lchild), getHeight(temp ->rchild)) + 1;
*root = temp;
}
void llRotation(TreeNode *node, TreeNode **root){
TreeNode *temp = node ->lchild;
node ->lchild = temp ->rchild;
temp ->rchild = node;
node ->height = max(getHeight(node ->lchild), getHeight(node ->rchild)) + 1;
temp ->height = max(getHeight(temp ->lchild), getHeight(temp ->rchild)) + 1;
*root = temp;
}
void avlInsert(TreeNode **T, int data){
if (*T == NULL){
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = data;
(*T) -> height = 0;
(*T) -> lchild = NULL;
(*T) -> rchild = NULL;
}
else if(data < (*T)->data ){
avlInsert(&((*T)->lchild), data);
int lheight = getHeight((*T) ->lchild);
int rheight = getHeight((*T) ->rchild);
if (lheight - rheight == 2){
if (data < (*T) -> lchild ->data){
llRotation(*T, T);
}
else{
rrRotation((*T)->lchild, &(*T)->lchild);
llRotation(*T, T);
}
}
}
else if(data > (*T)->data ){
avlInsert(&((*T)->rchild), data);
int lheight = getHeight((*T) ->lchild);
int rheight = getHeight((*T) ->rchild);
if (rheight - lheight == 2){
if (data > (*T) -> rchild ->data){
rrRotation(*T, T);
}
else{
llRotation((*T)->rchild, &(*T)->rchild);
rrRotation(*T, T);
}
}
}
(*T) ->height = max(getHeight((*T) ->lchild), getHeight((*T) ->rchild)) + 1;
}
void preOrder(TreeNode *T){
if(T){
printf("%d ", T->data);
preOrder(T ->lchild);
preOrder(T ->rchild);
}
}
int main(){
int i = 0;
TreeNode* T = NULL;
int num[5] = {5,4,3,2,1};
for(i; i<5; i++){
avlInsert(&T, num[i]);
}
preOrder(T);
}