平衡二叉树,插入,删除,C源码

转载请注明出处玮璘博客:http://www.wangweilin.name/rj_454.html
概念就是模型,写写吧:平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

 

就以下三遍文章足以。。

 

一篇可以让你知道如果写自己平衡二叉树的文章,学习平衡二叉事时看的第一篇,里面有作者的源码,可惜没看懂,但是道理写的很浅显。。

http://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html

 

这遍文章纯代码,看完上面的理论,下面的代码不难理解,我的代码就是模仿下面文章中的代码,但是里面并没有实现删除操作。。

http://wenku.baidu.com/view/bd511036f111f18583d05aec.html

 

这遍文章中的图型,和平衡二叉树例子,可以直观的告诉你进行平衡时的代码如何写,纯脑子想象去平衡节点是很困难的。。

http://wenku.baidu.com/view/e3bc9e0bf78a6529647d534d.html

 

代码还是写的不是很好,仅供参考。。

 

#include <stdio.h>
#include <stdlib.h>
//平衡因子
#define LEFT_HIGH    1
#define EVEN_HIGH    0
#define RIGHT_HIGH  -1
//每次插入或删除,只有一颗最小子树不平衡
#define BALANCE      0

typedef char Key_t;

typedef struct treeNode
{
    Key_t key;
    char bf;
    struct treeNode *left, *right;
    struct treeNode *parent;
}Tnode;

int balance;//不得已定义的全局变量,用于判断树是否已经平衡
//查到指定key的Tnode结点
Tnode *search(Tnode *root, Key_t key)
{
    if(NULL == root)
        return NULL;
    if(key > root->key)
        return search(root->right, key);
    else if(key < root->key)
        return search(root->left, key);
    else 
        return root;
}
//查找一个P节点的前驱节点
Tnode *search_former(Tnode *p)
{
    if(NULL == p)
        return p;
//P结点有左子树,此左子树下的最右子树便是P的前驱
    if(p->left){
        p = p->left;
        while(p->right)
            p = p->right;
        return p;
    }else{
//P没有左子树,向上查找到,第一个开始折向右边的结点便是P的前驱
        while(p->parent){
            if(p->parent->right == p)
                break;
            p = p->parent;
        }
        return p->parent;
    }
}
//查找一个P节点的后继节点
Tnode *search_latter(Tnode *p)
{
    if(NULL == p)
        return p;
//P结点有右子树,此右子树下的最左子树便是P的后继
    if(p->right){
        p = p->right;
        while(p->left)
            p = p->left;
        return p;
    }else{
//P没有右子树,向上查找到,第一个开始折向左边的结点便是P的后继
        while(p->parent){
            if(p->parent->left == p)
                break;
            p = p->parent;
        }
        return p->parent;
    }
}
//根节点为-2,即右子树插入或左子树有删除导致的不平衡,左旋转
void turn_left(Tnode **root)
{
    Tnode *right = (*root)->right;
//旋转后处理旋转节点的父节点
    right->parent = (*root)->parent;
    (*root)->parent = right;
    if(right->left != NULL)
        right->left->parent = (*root);
//左旋操作
    (*root)->right = right->left; 
    right->left = (*root);
    (*root) = right;
    return;
}
//根节点为-2,即右子树插入或左子树有删除导致的不平衡,左旋转
void turn_right(Tnode **root)
{
    Tnode *left = (*root)->left;
//旋转后处理旋转节点的父节点
    left->parent = (*root)->parent;
    (*root)->parent = left;
    if(left->right != NULL)
        left->right->parent = (*root);
//右旋操作
    (*root)->left = left->right;
    left->right = (*root);
    (*root) = left;
    return;
}
//左平衡操作
void left_balance(Tnode **root)
{
    
   Tnode *left = (*root)->left; 
   Tnode *lright; 

   switch(left->bf){
//root的bf为1,若root的left为1时,即root为2,然后进行右旋,此时3个节点像符号 /,L型
       case LEFT_HIGH:
           (*root)->bf = left->bf = EVEN_HIGH;
           turn_right(root);
         break;
//root的bf为1,若root的left也为-1时,即root为2,左高,此时3个节点像符号 <,LR型
       case RIGHT_HIGH:
           lright = left->right;
//分成3种情况来处理3个节点的平衡因子
           switch(lright->bf){
               case LEFT_HIGH:
                   (*root)->bf = RIGHT_HIGH;
                   left->bf = EVEN_HIGH;
                 break;
               case EVEN_HIGH:
                    (*root)->bf = left->bf = EVEN_HIGH;
                 break;
               case RIGHT_HIGH:
                    (*root)->bf = EVEN_HIGH;
                    left->bf = LEFT_HIGH;
                 break;
           }
           lright->bf = EVEN_HIGH;
//左旋然后右旋,即LR型
           turn_left(&(*root)->left);
           turn_right(root);
          break;
   }

}
//右平衡操作
void right_balance(Tnode **root)
{ 
   Tnode *right = (*root)->right; 
   Tnode *rleft; 

   switch(right->bf){
//root的bf为-1,若root的right为1时,即root为-2,然后进行右左旋,此时3个节点像符号 <,RL型
       case LEFT_HIGH:
           rleft = right->left;
//分成3种情况来处理3个节点的平衡因子
           switch(rleft->bf){
               case LEFT_HIGH:
                   (*root)->bf = EVEN_HIGH;
                   right->bf = RIGHT_HIGH;
                 break;
               case EVEN_HIGH:
                    (*root)->bf = right->bf = EVEN_HIGH;
                 break;
               case RIGHT_HIGH:
                    (*root)->bf = LEFT_HIGH;
                    right->bf = EVEN_HIGH;
                 break;
           }
           rleft->bf = EVEN_HIGH;
           turn_right(&(*root)->right);
           turn_left(root);
         break;
//root的bf为-1,若root的right为-1时,即root为-2,然后进行左旋,此时3个节点像符号 \,R型
       case RIGHT_HIGH:
          (*root)->bf = right->bf = EVEN_HIGH;
           turn_left(root);
         break;
   }
}
//dele_AVL_node删除节点中调用,用于删除节点
void part_of_dele(Tnode **root, Tnode *p)
{
//没有左右子节点时,直接删除P结点,要将在P的父指向P的指针要置空
    if(!p->left && !p->right){
//如果P节点的父节点不为空,即P不是根节点
        if(p->parent){
            if(p == p->parent->left)
                p->parent->left = NULL;
            else if(p == p->parent->right)
                p->parent->right = NULL;
        }else{
            *root = NULL;
        }
    }
//P有左节点,没有右节点时,分三种情况
    else if(p->left && !p->right){
//P为根节点,设置根节点为p->left
        if(!p->parent){
            *root = p->left;
        }
 //P为父节点的左分支,将p->left的父节点指向P的父节点,p父节点左分支指向p->left
        else if(p == p->parent->left){
            p->parent->left = p->left;
            p->left->parent = p->parent;
        }
//P为父节点的右分支,将p->left的父节点指向P的父节点,p父节点右分支指向p->left
        else if(p == p->parent->right){
            p->parent->right = p->left;
            p->left->parent = p->parent;
        }
    }
//P有右节点,没有左节点时,分三种情况
    else if(!p->left && p->right){
        if(!p->parent){
            *root = p->right;
        }
//P为父节点的左分支,将p->right的父节点指向P的父节点,p父节点左分支指向p->right
        else if(p == p->parent->left){
            p->parent->left = p->right;
            p->right->parent = p->parent;
        }
//P为父节点的右分支,将p->right的父节点指向P的父节点,p父节点右分支指向p->right
        else if(p == p->parent->right){
            p->parent->right = p->right;
            p->right->parent = p->parent;
        }
    }
    free(p);
    return;
}

//删除平衡二叉树节点
void dele_AVL_node(Tnode **root, Key_t key)
{
//如果*root为NULL,即没有找到对应要删除的KEY值节点
    if(NULL == *root){
        balance = BALANCE;
        return;
    }
//若key小于root,则在左分支中查找
    else if(key < (*root)->key){
        dele_AVL_node(&(*root)->left, key);
//判断是否失衡
        if(balance)
//删除操作的平衡操作
            switch((*root)->bf){
                case LEFT_HIGH:
                    (*root)->bf = EVEN_HIGH;
                    balance = !BALANCE;
                    break;
                case EVEN_HIGH:
                    (*root)->bf = RIGHT_HIGH;
                    balance = BALANCE;
                    break;
                case RIGHT_HIGH:
                    right_balance(root);
                    balance = BALANCE;
                    break;
            }
    }
//若key大于root,则在右分支中查找
    else if((*root)->key < key){
        dele_AVL_node(&(*root)->right, key);
//判断是否失衡
        if(balance)
//删除操作的平衡操作
            switch((*root)->bf){
                case LEFT_HIGH:
                    left_balance(root);
                    balance = BALANCE;
                    break;
                case EVEN_HIGH:
                    (*root)->bf = LEFT_HIGH;
                    balance = BALANCE;
                    break;
                case RIGHT_HIGH:
                    (*root)->bf = EVEN_HIGH;
                    balance = !BALANCE;
                    break;
        }
    }
//查到要删除的节点
    else{
//若节点有左右子树,刚找到此节点的前驱,对此前驱进行递归删除,并将前驱值覆盖删除的节点值
        if((*root)->left && (*root)->right){
            Tnode *q = search_former(*root);
            Tnode *ptr = *root;
            Key_t bak = q->key;
            dele_AVL_node(root, q->key);
            ptr->key = bak;
        } 
//没有左右子树时,则直接删除节点,并告知树失衡
        else {
            part_of_dele(&(*root)->parent, *root);
            balance = !BALANCE;
        }
    }

    return;
}
//插入操作的递归及平衡部分
void part_of_insert(Tnode **root, Tnode *p)
{
//*root为NULL时,代表找到要插入的位置,设置失衡
    if(NULL == *root){
        p->parent = NULL;
        *root = p;
        balance = !BALANCE;
        return;
    }
//p->key小于root->key,刚在左分支查找
    else if(p->key < (*root)->key){
//找到要插入的位置,设置失衡,下面会接着进行平衡操作
        if(NULL == (*root)->left){ 
            p->parent = *root;
            (*root)->left = p;
            balance = !BALANCE;
        } 
//有左支树,则接着在左子树查找
        else{
            part_of_insert(&(*root)->left, p);
        }
//插入时的平衡操作
        if(balance)
            switch((*root)->bf){
                case LEFT_HIGH:
                    left_balance(root);
                    balance = BALANCE;
                    break;
                case EVEN_HIGH:
                    (*root)->bf = LEFT_HIGH;
                    balance = !BALANCE;
                    break;
                case RIGHT_HIGH:
                    (*root)->bf = EVEN_HIGH;
                    balance = BALANCE;
                    break;

            }
        return;
    }
//p->key大于root->key,刚在右分支查找
    else if((*root)->key <= p->key){
//找到要插入的位置,设置失衡,下面会接着进行平衡操作
        if(NULL == (*root)->right){
            p->parent = *root;
            (*root)->right = p;
            balance = !BALANCE;
        }
//有左支树,则接着在左子树查找
        else{
            part_of_insert(&(*root)->right, p);
        }
//插入时的平衡操作
        if(balance)
            switch((*root)->bf){
                case LEFT_HIGH:
                    (*root)->bf = EVEN_HIGH;
                    balance = BALANCE;
                    break;
                case EVEN_HIGH:
                    (*root)->bf = RIGHT_HIGH;
                    balance = !BALANCE;
                    break;
                case RIGHT_HIGH:
                    right_balance(root);
                    balance = BALANCE;
                    break;
            }
        return;
    }

    return;
}
//节点插入函数
int insert_AVL_node(Tnode **root, Key_t key)
{
    Tnode *p = (Tnode *)malloc(sizeof(Tnode));
    if(NULL == p)  return -1;

    p->key = key;
    p->left = p->right = NULL;
//新插入的节点是平衡的
    p->bf = EVEN_HIGH;
    balance = !BALANCE;

    part_of_insert(root, p);

    return 0;
}
//后序摧毁二叉树
void destroy_tree(Tnode **root)
{
    if(!*root)
        return;
    destroy_tree(&(*root)->left);
    destroy_tree(&(*root)->right);
    free(*root);
    *root = NULL;
    return;
}
//通过数组生成平衡二叉树,root根节点,table数组指针,count数组大小
int create_AVL(Tnode **root, Key_t *table, int counts)
{
    int i;
    int ret = -1;
    
    *root = NULL;
    for(i = 0; i < counts; ++i){
        ret = insert_AVL_node(root, table[i]);
        if(ret < 0)
            break;
    }

    return ret;
}
//中序遍历二叉树
void mid_order(Tnode *root)
{
    if(root == NULL)
        return;

    mid_order(root->left);
    printf("|%d[%d] p:%d| ", root->key, root->bf, root->parent ? root->parent->key:-1);
    mid_order(root->right);

    return;
}
//树深度
int depth_of_tree(Tnode *root)
{
    int h, lh, rh;

    if(root == NULL)
        h = 0;
    else{
        lh = depth_of_tree(root->left);
        rh = depth_of_tree(root->right);
        if(lh > rh)
            h = lh + 1;
        else
            h = rh + 1;
    }

    return h;
}

int main()
{
    Key_t table[] = {4,5,7,2,1,3,6};
    Tnode *root = NULL;
    int h;

    create_AVL(&root, table, sizeof(table)/sizeof(table[0]));
   // insert_AVL_node(&root, 4);
   // dele_AVL_node(&root, 2);
   // dele_AVL_node(&root, 6);
#if 1
    dele_AVL_node(&root, 4);
    mid_order(root);
    printf("\n");
    dele_AVL_node(&root, 1);
    mid_order(root);
    printf("\n");
    dele_AVL_node(&root, 6);
    mid_order(root);
    printf("\n");
#endif
    dele_AVL_node(&root, 3);
    mid_order(root);
    printf("\n");
    h = depth_of_tree(root);
    printf("depth:%d\n", h);
    destroy_tree(&root);
    h = depth_of_tree(root);
    printf("depth:%d\n", h);
    return 0;
}
    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/qq160816/article/details/43275325
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞