数据结构之平衡二叉树详解

这篇具有很好参考价值的文章主要介绍了数据结构之平衡二叉树详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

平衡二叉树的定义:

平衡二叉树(balanced binary tree)

又称AVL树(Adelson-Velskii and Landis)

一棵平衡二叉树或者是空树,或者是具有下列性质的二叉排序树

        1,左子树与右子树的高度之差的绝对值小于等于1;

        2,左子树和右子树也是平衡二叉排序树.

为了方便起见,给每个结点附加一个数字,给出该结点左子树与右子树的高度差.这个数字称为结点的平衡因子(BF).

平衡因子 = 结点左子树的高度 - 结点右子树的高度

根据平衡二叉树的定义,平衡二叉树上所有结点的平衡因子只能是-1,0,或1.

例:

平衡二叉树,数据结构和算法,数据结构,算法,图论

对于一棵有n个结点的AVL树,其高度保持在O(log2^n)数量级

失衡二叉排序树的分析与调整

        当我们在一个平衡二叉排序树上插入一个结点时,有可能导致失衡,不再是一个平衡二叉排序树,即出现平衡因子绝对值大于1的结点.

平衡二叉树,数据结构和算法,数据结构,算法,图论

 如果在一棵AVL树中插入一个新结点后造成失衡,则必须重新调整树的结构,使之恢复平衡

平衡调整的四种类型:

平衡二叉树,数据结构和算法,数据结构,算法,图论

具体的调整为:

平衡二叉树,数据结构和算法,数据结构,算法,图论

调整原则为:1)降低高度 2)保持二叉排序树的性质

规律:按照二叉排序树的性质,挑选3个值的中间值作为调整后的根结点,最小值为根结点的左孩子,最大值为根结点的右孩子. 

例:LL型

平衡二叉树,数据结构和算法,数据结构,算法,图论

例:RL型

平衡二叉树,数据结构和算法,数据结构,算法,图论

RR型和LR型和上面类似,就不多介绍了,总之,一个总的原则,就是调整后必须保证1)降低高度 2)保持二叉排序树的性质

还是那句话,只要知道调整类型,就可以确定A,B,C三个顶点的位置,中间值为根结点,最大值为右孩子,最小值为左孩子,确定好后,别的结点就很容易根据二叉排序树的特点找到各自的位置,网上看了很多左旋,右旋,左右旋,头都晕.只要知道这个规律,不用管什么旋,也不用死记硬背还怕忘.随时碰到随时都可以马上上手.

接下来用代码来实现一个平衡二叉树的建立:

例题:输入关键字序列(16,3,7,11,9,26,18,14,15),创建一个平衡二叉树

第一个方法是给结点加了一个parent域,方便查找,不过感觉挺麻烦的,每次调整都要给parent域赋值,不过这个代码在有多个失衡点时会挑选最小代价树的失衡点,不管失衡点是不是根结点都是通用的文章来源地址https://www.toymoban.com/news/detail-779250.html

#include <stdio.h>
#include <stdlib.h>
#define MAXINT 10000
#define MAXSIZE 10
typedef struct BBTnode{
    int data;//这里为了方便,直接用int,没有用结构体.
    int balance;//平衡因子
    struct BBTnode* lchild;
    struct BBTnode* rchild;
    struct BBTnode* parent;
}BBTnode,*BBTree;
BBTree MinBalance;//最小失衡结点地址
int k = 0;
int i = 0;
BBTree SearchBBT(BBTree T, int m, char* arr)//计算从某点出发,到指定数字的路径
{
    if(!T || T->data == m)
    {
        return T;
    }
    else if(m < T->data)
    {
        arr[k++] = 'L';
        return SearchBBT(T->lchild, m, arr);
    }
    else
    {
        arr[k++] = 'R';
        return SearchBBT(T->rchild, m, arr);
    }

}

int CountNodes(BBTree T)//计算树中的结点数,比较失衡结点树的大小,选择较小的树(当不止一个失衡点时)
{
    if(!T)
    {
        return 0;
    }
    return CountNodes(T->lchild) + CountNodes(T->rchild) + 1;
}

int DepthBBT(BBTree T)//计算平衡二叉树的深度
{
    int m, n;
    if(!T)
    {
        return 0;
    }
    else
    {
        m = DepthBBT(T->lchild) + 1;//左边的深度
        n = DepthBBT(T->rchild) + 1;//右边的深度
    }
    if(m > n)return m;//取较大值
    else return n;
}


void OrderBBT(BBTree* T, BBTree Unbalance[MAXSIZE])//中序遍历二叉排序树,更新各结点平衡因子,把所有失衡点存储起来
{
    if(*T == NULL)return;
    else
    {
        OrderBBT(&(*T)->lchild,Unbalance);
        (*T)->balance = abs(DepthBBT((*T)->lchild) - DepthBBT((*T)->rchild));//计算该结点平衡因子,左边深度-右边深度再取绝对值
        if((*T)->balance>1)
        {
            Unbalance[i++] = *T;
        }
        OrderBBT(&(*T)->rchild,Unbalance);
    }
}

void AddBBT(BBTree* T, int m, BBTree parent)//二叉排序树的递归添加元素
{
    if(!(*T))
    {
        *T = malloc(sizeof(BBTnode));
        (*T)->data = m;
        (*T)->lchild = NULL;
        (*T)->rchild = NULL;
        (*T)->balance = 0;
        (*T)->parent = parent;
    }
    else if(m < (*T)->data)
    {
        AddBBT(&(*T)->lchild, m, *T);
    }
    else
    {
        AddBBT(&(*T)->rchild, m, *T);

    }
}


void creatBBT(BBTree* T)//创建平衡二叉排序树,实际上就是给一个空树添加元素
{
    int input = 1;
    BBTree A,B,C;//定义图示中表示的三个顶点
    while(input)
    {
        printf("请依次输入数字序列,输入完毕以0结束:>");
        scanf("%d",&input);
        if(input == 0)break;
        AddBBT(T, input,*T);
        MinBalance = 0;//重置最小平衡因子为空
        int temp = MAXINT;
        int j;
        BBTree Unbalance[MAXSIZE] = {0};//定义一个失衡结点数组,用来存放当前树中存在的失衡结点
        i = 0;//重置数组Unbalance的下标为0开始
        OrderBBT(T,Unbalance);//更新平衡因子,得到平衡因子数组Unbalance
        for(j = 0; j < MAXSIZE; j++)//从数组Unbalance找出最小失衡因子,并返回该地址到MinBalance
        {
            if(!Unbalance[j])break;
            if(CountNodes(Unbalance[j]) < temp)
            {
                temp = CountNodes(Unbalance[j]);
                MinBalance = Unbalance[j];
            }
        }
        char ChoiceType[MAXSIZE] = {0};//选择调整类型的数组(LL,RR.LR,RL)
        k = 0;//重置SearchBBT里的k变量
        SearchBBT(MinBalance, input, ChoiceType);//得到从失衡点出发到添加结点间的路径
        if(ChoiceType[0] == 'L' && ChoiceType[1] == 'L')//LL型调整
        {
            A = MinBalance;
            B = MinBalance->lchild;
            C = MinBalance->lchild->lchild;
            if(A->parent)//如果这个失衡点不是根结点
            {
                if(A->data < A->parent->data)A->parent->lchild = B;
                else A->parent->rchild = B;
            }
            else *T = B;

            A->lchild = B->rchild;
            if(B->rchild)B->rchild->parent = A;
            B->rchild = A;
            B->parent = A->parent;
            A->parent = B;

        }
        else if(ChoiceType[0] == 'R' && ChoiceType[1] == 'R')//RR型调整
        {
            A = MinBalance;
            B = MinBalance->rchild;
            C = MinBalance->rchild->rchild;
            if(A->parent)//如果这个失衡点不是根结点
            {
                if(A->data < A->parent->data)A->parent->lchild = A->rchild;
                else A->parent->rchild = A->rchild;
            }
            else *T = B;//如果是根结点,那么根结点变成调整后的根结点
            A->rchild = B->lchild;
            if(B->lchild)B->lchild->parent = A;
            B->lchild = A;
            B->parent = A->parent;
            A->parent = B;



        }
        else if(ChoiceType[0] == 'L' && ChoiceType[1] == 'R')//LR型调整
        {
            A = MinBalance;
            B = MinBalance->lchild;
            C = MinBalance->lchild->rchild;
            if(A->parent)//如果这个失衡点不是根结点
            {
                if(A->data < A->parent->data)A->parent->lchild = C;
                else A->parent->rchild = C;
            }
            else *T = C;
            B->rchild = C->lchild;
            if(C->lchild)C->lchild->parent =B;
            A->lchild = C->rchild;
            if(C->rchild)C->rchild->parent = A;
            C->rchild = A;
            C->lchild = B;
            C->parent = A->parent;
            A->parent = C;
            B->parent = C;

        }
        else if(ChoiceType[0] == 'R' && ChoiceType[1] == 'L')//RL型调整
        {
            A = MinBalance;
            B = MinBalance->rchild;
            C = MinBalance->rchild->lchild;
            if(A->parent)//如果这个失衡点不是根结点
            {
                if(A->data < A->parent->data)A->parent->lchild = C;
                else A->parent->rchild = C;
            }
            else *T = C;
            A->rchild = C->lchild;
            if(C->lchild)C->lchild->parent = A;
            B->lchild = C->rchild;
            if(C->rchild)C->rchild->parent = B;
            C->lchild = A;
            C->rchild = B;
            C->parent = A->parent;
            A->parent = C;
            B->parent = C;
        }
    }
    BBTree arr[MAXSIZE] = {0};//这个只为为了下面这个OrderBBT函数能运行,没有别的意义
    OrderBBT(T,arr);
}
void printBBT(BBTree T)//中序输出二叉排序树,得到的是一个递增数列
{
    if(T == NULL)return;
    else
    {
        printBBT(T->lchild);
        printf("%d号结点平衡因子为%d\n",T->data,T->balance);
        printBBT(T->rchild);
    }
}

int main()
{
    BBTree T = NULL;//定义二叉排序树T
    creatBBT(&T);//创建二叉排序树
    printBBT(T);//输出创建好的二叉排序树
    return 0;
}

到了这里,关于数据结构之平衡二叉树详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】平衡二叉树

    需要云服务器等云产品来学习Linux的同学可以移步/--腾讯云--/--阿里云--/--华为云--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。   目录 一、平衡二叉树的介绍 二、平衡二叉树的插入 1、平衡二叉树的插入步骤 2、平衡二叉树的旋转 2.1左单旋 2.2右单旋 2

    2024年02月03日
    浏览(75)
  • 数据结构之二叉树和平衡二叉树

    1、二叉树: 2、平衡二叉树:

    2024年04月17日
    浏览(33)
  • 数据结构之平衡二叉树的平衡调整

    1:LL型调整 2:RR型调整 3:LR型调整 4:RL型调整 5:总结 作者约定:将导致不平衡的结点称作 被破坏者 ,破坏了结点的平衡的结点成为 破坏者 ,经过调整可以让该树平衡的结点称为 调整结点 。 LL型不平衡调整方法:以调整结点为中心,进行右旋操作,就可以使树平衡。

    2024年02月09日
    浏览(33)
  • 数据结构与算法之《二叉树》详解

    文章目录 一、树的概念及结构 二、二叉树的概念及结构 2、1 二叉树的概念 2、2 二叉树的特点 2、3 二叉树的结构(图片) 2、4 特殊的二叉树 三、二叉树的代码及思路实现 3、1 二叉树的存储结构 3、1、1 二叉树的顺序存储结构 3、1、2 二叉树的链式存储结构 3、2 二叉树链式

    2024年02月01日
    浏览(37)
  • 【数据结构】二叉排序树——平衡二叉树的调整

    参考视频: 懒猫老师-数据结构-(59)平衡二叉树【互动视频】 (1)什么是平衡二叉树 平衡二叉树(Balanced Binary Tree)是一种特殊的二叉查找树,它的目的是保持树的高度尽量平衡,以保证查找、插入、删除等操作的时间复杂度为 O(log n)。 常见的平衡二叉树算法包括 AVL 树、红

    2024年02月04日
    浏览(32)
  • 【数据结构】二叉树的遍历递归算法详解

    我们来写一个函数 BuyNode(x)函数 用于创建二叉树结点。 用动态开辟函数 malloc 函数进行动态开辟,并强制转换为 BTNode 型,用变量 node 来去管理开辟的空间。 我们初始化结点,其 val 即为传入的参数x,左右指针 left 和 right 都设为NULL。 我们在主函数中创建上面这样一颗二叉树

    2024年01月20日
    浏览(33)
  • 【数据结构与算法篇】深入浅出——二叉树(详解)

    ​👻内容专栏:《数据结构与算法专栏》 🐨本文概括: 二叉树是一种常见的数据结构,它在计算机科学中广泛应用。本博客将介绍什么是二叉树、二叉树的顺序与链式结构以及它的基本操作,帮助读者理解和运用这一重要概念。 🐼本文作者: 花 蝶 🐸发布时间:2023.6.5

    2024年02月08日
    浏览(33)
  • 数据结构与算法——树与二叉树篇详解

    树形结构是一种非常重要的 非线性结构 ,树形结构中数据元素之间具有 一对多 的逻辑关系。 1.1.1 树的定义 树是由n(n=0)个结点所构成的有限集合 当n=0时,称为空树 当n0时,n个结点满足以下条件 有且仅有一个称为根的结点 其余结点可分为m个互不相交的有限集合,且每一个

    2024年02月06日
    浏览(43)
  • 数据结构——常见二叉树的分类(完全二叉树、满二叉树、平衡二叉树、二叉搜索树、红黑树)

    专业术语 中文 描述 Root 根节点 一棵树的顶点 Child 孩子结点 一个结点含有的子树的根节点称为该结点的子节点 Leaf 叶子结点 没有孩子的节点 Degree 度 一个节点包含子树的数量 Edge 边 一个节点与另外一个节点的连接 Depth 深度 根节点到这个节点经过边的数量 Height 节点高度 从

    2024年02月03日
    浏览(34)
  • 数据结构-各种树(二叉树、二叉查找树、平衡二叉树、红黑树、B树、B+树)

    概念:二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树 特点:每个

    2024年02月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包