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

来源:互联网 发布:网上车市数据运维 编辑:程序博客网 时间:2024/05/17 09:36

转载请注明出处玮璘博客: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      0typedef 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;}
0 0
原创粉丝点击