平衡二叉树(C语言)

我觉得这个是最通俗易懂的版本了,,改编自网上,,出处忘了,我完整了他的代码,并把风格改成我的了,,函数实在不喜欢一股脑的全部扔上面,。,,,。

建议阅读这两篇文章:

http://www.cnki.net/KCMS/detail/detail.aspx?QueryID=2&CurRec=1&recid=&filename=GWDT201034126&dbname=CJFDN0911&dbcode=CJFR&pr=CJFR2010;CFJD2010;&urlid=&yx=&uid=WEEvREcwSlJHSldRa1FiNlpyakNuRFRyd0tkTUkwazlLWW5tbjYzYXFVV3pDK3pWYjBQN3ZZNjdKQTlVQkpWN3l3PT0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4IQMovwHtwkF4VYPoHbKxJw!!&v=MDAyOTJGeURsVzd2SUlqclBlckc0SDlIUHE0NUhZb1I4ZVgxTHV4WVM3RGgxVDNxVHJXTTFGckNVUkw2ZVplZHE=

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

#include<stdio.h>
#include<stdlib.h>
#define EH 0            /*等高*/
#define LH 1            /*左高*/
#define RH -1            /*右高*/

typedef int ElemType;                 /*数据类型*/

typedef struct BiTree{
    ElemType data;                    /*数据元素*/
    int BF;                         /*平衡因子*/
    struct BiTree *lchild,*rchild;     /*左右子女指针*/
}*Bitree,BitreeNode;

int InsertAVL(Bitree *T,ElemType e,bool *taller);
void LeftBalance(Bitree *T);
void RightBalance(Bitree *T);
void R_Rotate(Bitree *T);
void L_Rotate(Bitree *T);
bool *taller=(bool*)malloc(sizeof(bool));

int main(void)
{
    int data;
    Bitree T=NULL;
    while(1)
    {
        printf("enter the number(zero to exit):");
        scanf("%d",&data);
        if(0==data)break;
        InsertAVL(&T,data,taller);

    }

    return 0;
}

/*若在平衡的二叉排序树T 中不存在和e 有相同关键码的结点,则插入一个数据元素为e 的*/
/*新结点,并反回1,否则反回0。若因插入而使二叉排序树失去平衡,则作平衡旋转处理,*/
/*布尔型变量taller 反映T 长高与否*/
int InsertAVL(Bitree *T,ElemType e,bool *taller)
{
    if(!*T)                /*插入新结点,树“长高”,置taller 为TURE*/
    {
        (*T)=(Bitree)malloc(sizeof(BitreeNode));
        (*T)->data = e;
        (*T)->lchild = (*T)->rchild = NULL;
        (*T)->BF = EH;
        *taller = true;
    }
    else
    {
        if(e==(*T)->data)        /*树中存在和e 有相同关键码的结点,不插入*/
        {
            *taller = false;
            return 0;
        }
        if(e<(*T)->data)
        {
            if(!InsertAVL(&(*T)->lchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {
                case EH :                    /*原本左、右子树等高,因左子树增高使树增高*/
                    (*T)->BF=LH;
                    *taller=true;
                    break;

                case LH :                    /*原本左子树高,需作左平衡处理*/
                    LeftBalance(T);
                    *taller=false;
                    break;

                case RH :                    /*原本右子树高,使左、右子树等高*/
                    (*T)->BF=EH;
                    *taller=false;
                    break;

            }

        }
        else
        {
            if(!InsertAVL(&(*T)->rchild,e,taller))    return 0;  /*未插入*/
            if(*taller)
            switch((*T)->BF)
            {
                case EH :                    /*原本左、右子树等高,因右子树增高使树增高*/
                    (*T)->BF=RH;
                    *taller=true;
                    break;

                case LH :                    /*原本左子树高,使左、右子树等高*/
                    (*T)->BF=EH;
                     *taller=false;
                     break;

                case RH :                    /*原本右子树高,需作右平衡处理*/
                    RightBalance(T);
                    *taller=false;
                     break;

            }
        }
    }
    return 1;
}

/*对以*p 指向的结点为根的子树,作左平衡旋转处理,处理之后,*p 指向的结点为子树的新根*/
void LeftBalance(Bitree *T)
{
    Bitree L=(*T)->lchild,Lr;             /*L 指向*T左子树根结点*/
    switch(L->BF)                /*检查L 平衡度,并作相应处理*/
    {
        case LH:                    /*新结点插在*p 左子树的左子树上,需作单右旋转处理*/
            (*T)->BF=L->BF=EH;
             R_Rotate(T);
             break;
        case EH:             /*原本左、右子树等高,因左子树增高使树增高*/
            (*T)->BF=LH;    //这里的EH好像没有写的必要
              *taller=true;
              break;
        case RH:                     /*新结点插在*T 左孩子的右子树上,需作先左后右双旋处理*/
            Lr=L->rchild;             /*Lr 指向*p 左孩子的右子树根结点*/
            switch(Lr->BF)         /*修正*T 及其左子树的平衡因子*/
            {
                case LH:
                    (*T)->BF = RH;
                    L->BF = EH;
                    break;
                case EH:
                    (*T)->BF = L->BF= EH;
                    break;
                case RH:
                    (*T)->BF = EH;
                    L->BF = LH;
                    break;

            }
            Lr->BF = EH;
            L_Rotate(&L);        /*对*T 的左子树作左旋转处理*/
            R_Rotate(T);        /*对*T 作右旋转处理*/
    }
}
//这里和leftbalance一个道理,试着自己写一下
void RightBalance(Bitree *T)
{
    Bitree Lr= (*T)->rchild,L;
    switch(Lr->BF)
    {
        case EH:
            *taller = true;
            (*T)->BF = RH;
            break;
        case RH:
            (*T)->BF=Lr->BF=EH;
            L_Rotate(T);
            break;
        case LH:
            L = Lr->lchild;
            switch(L->BF)
            {
                case EH:
                    (*T)->BF=Lr->BF= EH;
                    break;
                case RH:
                    Lr->BF= EH;
                    (*T)->BF = LH;
                    break;
                case LH:
                    (*T)->BF = LH;
                    Lr->BF = EH;
                    break;

            }
            L->BF = EH;
            R_Rotate(&Lr);
            L_Rotate(T);    

    }
}

/*对以*T 指向的结点为根的子树,作右单旋转处理,处理之后,*T 指向的结点为子树的新根*/
void R_Rotate(Bitree *T)
{
    Bitree L=(*T)->lchild;                 /*L 指向*T 左子树根结点*/
    (*T)->lchild=L->rchild;                 /*L 的右子树挂接*T 的左子树*/
    L->rchild=*T; *T=L;             /* *L 指向新的根结点*/
}

/*对以*p 指向的结点为根的子树,作左单旋转处理,处理之后,*p 指向的结点为子树的新根*/
void L_Rotate(Bitree *T)
{
    Bitree Lr=(*T)->rchild;                 /*Lr 指向*T 右子树根结点*/
    (*T)->rchild=Lr->lchild;                 /*L 的左子树挂接*p 的右子树*/
    Lr->lchild=*T;
    *T=Lr;                                     /* *L 指向新的根结点*/
}
时间: 2024-11-05 22:03:24

平衡二叉树(C语言)的相关文章

平衡二叉树(AVL)的实现,附可运行C语言代码

最近几月一直在自学C语言和数据结构,先是写了排序二叉树,觉得平衡二叉树作为一个经典数据结构,有必要实现一下. 网上看了些资料,在AVL和红黑树之间考虑,最后个人还是倾向于AVL. 不同于标准AVL的是,笔者没有使用平衡因子,直接根据左右孩子的高度差值判断是否平衡.整个平衡二叉树是在普通二叉查找树的基础上修改得到的,对于学习数据结构的同学来说,这样逐步提高难度,写起来挑战性没那么大. 代码经测试是可以运行,并实现插入.删除.修改节点时都可以保持平衡.相对于普通二叉查找树,AVL在查找时效率高耗时短

数据结构之---C语言实现平衡二叉树(AVL树)

//AVL(自动平衡二叉树) #include <stdio.h> #include <stdlib.h> typedef int ElemType; //每个结点的平均值 typedef enum { EH = 0, LH = 1, RH = -1 }bh_t; typedef enum { FALSE = 0, TRUE = 1 }bool_t; //定义平衡二叉树 typedef struct BSTNode { ElemType key; //平衡值 int bf; str

平衡二叉树(AVL)c语言实现

参考: 二叉平衡树的插入和删除操作 平衡二叉树,AVL树之图解篇 [查找结构3]平衡二叉查找树 [AVL] #include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0

【C语言】平衡二叉树

AVL树简介 AVL树的名字来源于它的发明作者G.M. Adelson-Velsky 和 E.M. Landis.AVL树是最先发明的自平衡二叉查找树(Self-Balancing Binary Search Tree,简称平衡二叉树). 平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树. 一棵AVL树有如下必要条件: • 条件一:它必须是二叉查找树. • 条件二:每个节点的

一步一步写平衡二叉树(AVL树)

平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树.平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态.这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(

C 语言资源大全中文版

C 语言资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-c 是 koz.ross 发起维护的 C 语言资源列表,内容包括了:构建系统.编译器.数据库.加密.初中高的教程/指南.书籍.库等等. Awesome 系列虽然挺全,但基本只对收录的资源做了极为简要的介绍,如果有更详细的中文介绍,对相应开发者的帮助会更大.这也是我们发起这个开源项目的初衷. 我们要做什么? 基于 awesome-c 列表,我们将对其中的各个资源项进行

华为C语言笔试题集合

①华为笔试题搜集 1.static有什么用途?(请至少说明两种)    1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变.    2) 在模块内(但在函数体外),一个被声明为静态的变量能够被模块内所用函数訪问,但不能被模块外其他函数訪问.它是一个本地的全局变量.    3) 在模块内,一个被声明为静态的函数仅仅可被这一模块内的其他函数调用.那就是,这个函数被限制在声明它的模块的本地范围内使用 2.引用与指针有什么差别?    1) 引用必须被初始化,指针不必.    2)

经典c语言题

1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 2. 写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个. #define MIN(A,B) ((A) <= (B) ?(A) : (B)) 5. 用变量a给出下面的定义 a) 一个整型数(An integer) b) 一个指向整型数的指针(A pointer to an integer)

C语言面试及答案分析

第一部分:基本概念及其它问答题 1.关键字static的作用是什么? 这个简单的问题很少有人能回答完全.在C语言中,关键字static有三个明显的作用: 1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. 2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问.它是一个本地的全局变量. 3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用.那就是,这个函数被限制在声明它的模块的本地范围内使用. 大多