广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言平衡二叉树的示例分析
  • 833
分享到

C语言平衡二叉树的示例分析

2023-06-25 13:06:45 833人浏览 安东尼
摘要

这篇文章给大家分享的是有关C语言平衡二叉树的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一

这篇文章给大家分享的是有关C语言平衡二叉树的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

    平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

    C语言平衡二叉树的示例分析

    平衡二叉树大部分操作和二叉查找树类似,主要不同在于插入删除的时候平衡二叉树的平衡可能被改变,并且只有从那些插入点到根结点的路径上的结点的平衡性可能被改变,因为只有这些结点的子树可能变化。

    平衡二叉树不平衡的情形:

    把需要重新平衡的结点叫做α,由于任意两个结点最多只有两个儿子,因此高度不平衡时,α结点的两颗子树的高度相差2.容易看出,这种不平衡可能出现在下面4中情况中:

    对α的左儿子的左子树进行一次插入

    对α的左儿子的右子树进行一次插入

    对α的右儿子的左子树进行一次插入

    对α的右儿子的右子树进行一次插入

    C语言平衡二叉树的示例分析

    情形1和情形4是关于α的镜像对称,二情形2和情形3也是关于α的镜像对称,因此理论上看只有两种情况,但编程的角度看还是四种情形。

    第一种情况是插入发生在“外边”的情形(左左或右右),该情况可以通过一次单旋转完成调整;第二种情况是插入发生在“内部”的情形(左右或右左),这种情况比较复杂,需要通过双旋转来调整。

    调整措施:

    一、单旋转

    C语言平衡二叉树的示例分析

    上图是左左的情况,k2结点不满足平衡性,它的左子树k1比右子树z深两层,k1子树中更深的是k1的左子树x,因此属于左左情况。

    为了恢复平衡,我们把x上移一层,并把z下移一层,但此时实际已经超出了AVL树的性质要求。为此,重新安排结点以形成一颗等价的树。为使树恢复平衡,我们把k2变成这棵树的根节点,因为k2大于k1,把k2置于k1的右子树上,而原本在k1右子树的Y大于k1,小于k2,就把Y置于k2的左子树上,这样既满足了二叉查找树的性质,又满足了平衡二叉树的性质。

    这种情况称为单旋转。

    二、双旋转

    对于左右和右左两种情况,单旋转不能解决问题,要经过两次旋转。

    C语言平衡二叉树的示例分析

    对于上图情况,为使树恢复平衡,我们需要进行两步,第一步,把k1作为根,进行一次右右旋转,旋转之后就变成了左左情况,所以第二步再进行一次左左旋转,最后得到了一棵以k2为根的平衡二叉树。

    AVL树的删除操作:

    同插入操作一样,删除结点时也有可能破坏平衡性,这就要求我们删除的时候要进行平衡性调整。

    删除分为以下几种情况:

    首先在整个二叉树中搜索要删除的结点,如果没搜索到直接返回不作处理,否则执行以下操作:

    1.要删除的节点是当前根节点T。

    如果左右子树都非空。在高度较大的子树中实施删除操作。

    分两种情况:

    (1)、左子树高度大于右子树高度,将左子树中最大的那个元素赋给当前根节点,然后删除左子树中元素值最大的那个节点。

    (1)、左子树高度小于右子树高度,将右子树中最小的那个元素赋给当前根节点,然后删除右子树中元素值最小的那个节点。

    如果左右子树中有一个为空,那么直接用那个非空子树或者是NULL替换当前根节点即可。

    2、要删除的节点元素值小于当前根节点T值,在左子树中进行删除。

    递归调用,在左子树中实施删除。

    这个是需要判断当前根节点是否仍然满足平衡条件,

    如果满足平衡条件,只需要更新当前根节点T的高度信息。

    否则,需要进行旋转调整:

    如果T的左子节点的左子树的高度大于T的左子节点的右子树的高度,进行相应的单旋转。否则进行双旋转。

    3、要删除的节点元素值大于当前根节点T值,在右子树中进行删除。

    下面给出详细代码实现:

    AvlTree.h

    #include <iOStream>#include <alGorithm>using namespace std;#pragma once//平衡二叉树结点template <typename T>struct Avlnode{    T data;    int height; //结点所在高度    AvlNode<T> *left;    AvlNode<T> *right;    AvlNode<T>(const T theData) : data(theData), left(NULL), right(NULL), height(0){}};//AvlTreetemplate <typename T>class AvlTree{public:    AvlTree<T>(){}    ~AvlTree<T>(){}    AvlNode<T> *root;    //插入结点    void Insert(AvlNode<T> *&t, T x);    //删除结点    bool Delete(AvlNode<T> *&t, T x);    //查找是否存在给定值的结点    bool Contains(AvlNode<T> *t, const T x) const;    //中序遍历    void InorderTraversal(AvlNode<T> *t);    //前序遍历    void PreorderTraversal(AvlNode<T> *t);    //最小值结点    AvlNode<T> *FindMin(AvlNode<T> *t) const;    //最大值结点    AvlNode<T> *FindMax(AvlNode<T> *t) const;private:    //求树的高度    int GetHeight(AvlNode<T> *t);    //单旋转 左    AvlNode<T> *LL(AvlNode<T> *t);    //单旋转 右    AvlNode<T> *RR(AvlNode<T> *t);    //双旋转 右左    AvlNode<T> *LR(AvlNode<T> *t);    //双旋转 左右    AvlNode<T> *RL(AvlNode<T> *t);};template <typename T>AvlNode<T> * AvlTree<T>::FindMax(AvlNode<T> *t) const{    if (t == NULL)        return NULL;    if (t->right == NULL)        return t;    return FindMax(t->right);}template <typename T>AvlNode<T> * AvlTree<T>::FindMin(AvlNode<T> *t) const{    if (t == NULL)        return NULL;    if (t->left == NULL)        return t;    return FindMin(t->left);}template <typename T>int AvlTree<T>::GetHeight(AvlNode<T> *t){    if (t == NULL)        return -1;    else        return t->height;}//单旋转//左左插入导致的不平衡template <typename T>AvlNode<T> * AvlTree<T>::LL(AvlNode<T> *t){    AvlNode<T> *q = t->left;    t->left = q->right;    q->right = t;    t = q;    t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1;    q->height = max(GetHeight(q->left), GetHeight(q->right)) + 1;    return q;}//单旋转//右右插入导致的不平衡template <typename T>AvlNode<T> * AvlTree<T>::RR(AvlNode<T> *t){    AvlNode<T> *q = t->right;    t->right = q->left;    q->left = t;    t = q;    t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1;    q->height = max(GetHeight(q->left), GetHeight(q->right)) + 1;    return q;}//双旋转//插入点位于t的左儿子的右子树template <typename T>AvlNode<T> * AvlTree<T>::LR(AvlNode<T> *t){    //双旋转可以通过两次单旋转实现    //对t的左结点进行RR旋转,再对根节点进行LL旋转    RR(t->left);    return LL(t);}//双旋转//插入点位于t的右儿子的左子树template <typename T>AvlNode<T> * AvlTree<T>::RL(AvlNode<T> *t){    LL(t->right);    return RR(t);}template <typename T>void AvlTree<T>::Insert(AvlNode<T> *&t, T x){    if (t == NULL)        t = new AvlNode<T>(x);    else if (x < t->data)    {        Insert(t->left, x);        //判断平衡情况        if (GetHeight(t->left) - GetHeight(t->right) > 1)        {            //分两种情况 左左或左右            if (x < t->left->data)//左左                t = LL(t);            else                  //左右                t = LR(t);        }    }    else if (x > t->data)    {        Insert(t->right, x);        if (GetHeight(t->right) - GetHeight(t->left) > 1)        {            if (x > t->right->data)                t = RR(t);            else                t = RL(t);        }    }    else        ;//数据重复    t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1;}template <typename T>bool AvlTree<T>::Delete(AvlNode<T> *&t, T x){    //t为空 未找到要删除的结点    if (t == NULL)        return false;    //找到了要删除的结点    else if (t->data == x)    {        //左右子树都非空        if (t->left != NULL && t->right != NULL)        {//在高度更大的那个子树上进行删除操作            //左子树高度大,删除左子树中值最大的结点,将其赋给根结点            if (GetHeight(t->left) > GetHeight(t->right))            {                t->data = FindMax(t->left)->data;                Delete(t->left, t->data);            }            else//右子树高度更大,删除右子树中值最小的结点,将其赋给根结点            {                t->data = FindMin(t->right)->data;                Delete(t->right, t->data);            }        }        else        {//左右子树有一个不为空,直接用需要删除的结点的子结点替换即可            AvlNode<T> *old = t;            t = t->left ? t->left: t->right;//t赋值为不空的子结点            delete old;        }    }    else if (x < t->data)//要删除的结点在左子树上    {        //递归删除左子树上的结点        Delete(t->left, x);        //判断是否仍然满足平衡条件        if (GetHeight(t->right) - GetHeight(t->left) > 1)        {            if (GetHeight(t->right->left) > GetHeight(t->right->right))            {                //RL双旋转                t = RL(t);            }            else            {//RR单旋转                t = RR(t);            }        }        else//满足平衡条件 调整高度信息        {            t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1;        }    }    else//要删除的结点在右子树上    {        //递归删除右子树结点        Delete(t->right, x);        //判断平衡情况        if (GetHeight(t->left) - GetHeight(t->right) > 1)        {            if (GetHeight(t->left->right) > GetHeight(t->left->left))            {                //LR双旋转                t = LR(t);            }            else            {                //LL单旋转                t = LL(t);            }        }        else//满足平衡性 调整高度        {            t->height = max(GetHeight(t->left), GetHeight(t->right)) + 1;        }    }    return true;}//查找结点template <typename T>bool AvlTree<T>::Contains(AvlNode<T> *t, const T x) const{    if (t == NULL)        return false;    if (x < t->data)        return Contains(t->left, x);    else if (x > t->data)        return Contains(t->right, x);    else        return true;}//中序遍历template <typename T>void AvlTree<T>::InorderTraversal(AvlNode<T> *t){    if (t)    {        InorderTraversal(t->left);        cout << t->data << ' ';        InorderTraversal(t->right);    }}//前序遍历template <typename T>void AvlTree<T>::PreorderTraversal(AvlNode<T> *t){    if (t)    {        cout << t->data << ' ';        PreorderTraversal(t->left);        PreorderTraversal(t->right);    }}

    main.cpp

    #include "AvlTree.h"int main(){    AvlTree<int> tree;    int value;    int tmp;    cout << "请输入整数建立二叉树(-1结束):" << endl;    while (cin >> value)    {        if (value == -1)            break;        tree.Insert(tree.root,value);    }    cout << "中序遍历";    tree.InorderTraversal(tree.root);    cout << "\n前序遍历:";    tree.PreorderTraversal(tree.root);    cout << "\n请输入要查找的结点:";    cin >> tmp;    if (tree.Contains(tree.root, tmp))        cout << "已查找到" << endl;    else        cout << "值为" << tmp << "的结点不存在" << endl;    cout << "请输入要删除的结点:";    cin >> tmp;    tree.Delete(tree.root, tmp);    cout << "删除后的中序遍历:";    tree.InorderTraversal(tree.root);    cout << "\n删除后的前序遍历:";    tree.PreorderTraversal(tree.root);}

    测试结果

    C语言平衡二叉树的示例分析

    感谢各位的阅读!关于“C语言平衡二叉树的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

    --结束END--

    本文标题: C语言平衡二叉树的示例分析

    本文链接: https://www.lsjlt.com/news/305135.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • C语言平衡二叉树的示例分析
      这篇文章给大家分享的是有关C语言平衡二叉树的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。平衡二叉树(Balanced Binary Tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一...
      99+
      2023-06-25
    • C语言中二叉树的示例分析
      这篇文章主要为大家展示了“C语言中二叉树的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C语言中二叉树的示例分析”这篇文章吧。树概念及结构树是一种 非线性 的数据结构,它是由 n ( n...
      99+
      2023-06-29
    • C语言平衡二叉树详解
      目录调整措施:一、单旋转二、双旋转AVL树的删除操作:删除分为以下几种情况:1.要删除的节点是当前根节点T。2、要删除的节点元素值小于当前根节点T值,在左子树中进行删除。3、要删除的...
      99+
      2022-11-12
    • C语言之平衡二叉树详解
      目录什么是平衡二叉树平衡二叉树的基本特点为什么会出现平衡二叉树二叉树四种不平衡的情况C语言实现平衡二叉树什么是平衡二叉树 平衡二叉树是具有平衡属性的有序二叉树,所谓的平衡即当前树的左...
      99+
      2023-05-17
      C语言二叉树 C语言平衡二叉树
    • Java平衡二叉树实例分析
      这篇文章主要讲解了“Java平衡二叉树实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java平衡二叉树实例分析”吧!AVL树的引入搜索二叉树有着极高的搜索效率,但是搜索二叉树会出现以...
      99+
      2023-06-30
    • C语言平衡二叉树真题练习
      目录一、题目描述二、解题思路自顶向下的递归(暴力解法)自底向上的递归(最优解法)题目难度:简单 LeetCode链接:平衡二叉树 一、题目描述 给定一个二叉树,判断它是否是高度平衡的...
      99+
      2022-11-13
    • C语言平衡二叉树问题怎么解决
      这篇文章主要介绍“C语言平衡二叉树问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言平衡二叉树问题怎么解决”文章能帮助大家解决问题。一、题目描述给定一个二叉树,判断它是否是高度平衡的二...
      99+
      2023-06-30
    • Python实现二叉排序树与平衡二叉树的示例代码
      目录前言1. 二叉排序树1.1 构建一棵二叉排序树1.2 二叉排序树的数据结构1.3 实现二叉排序树类中的方法:2. 平衡二叉排序树2.1 二叉平衡排序树的数据结构3. 总结前言 什...
      99+
      2022-11-10
    • C语言二叉树的遍历示例介绍
           在本算法中先利用先序遍历创建了树,利用了递归的算法使得算法简单,操作容易,本来无printf("%c的左/右子树:", c...
      99+
      2022-11-12
    • C++树与二叉树实例分析
      这篇“C++树与二叉树实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++树与二叉树实例分析”文章吧。树树的定义Q:...
      99+
      2023-06-30
    • C++AVLTree高度平衡的二叉搜索树深入分析
      目录一、AVL树的概念二、AVL树节点的定义三、AVL树的插入四、AVL树的旋转1.左单旋2.右单旋3.左右双旋4.右左双旋五、进行验证六、AVLTree的性能一、AVL树的概念 二...
      99+
      2023-03-08
      C++ AVLTree二叉搜索树 C++高度平衡二叉搜索树
    • Java深入分析了解平衡二叉树
      目录AVL树的引入基本概念基础设计RR(左旋)LL(右旋)LR(先左旋再右旋)RL(先右旋再左旋)添加节点删除节点AVL树的引入 搜索二叉树有着极高的搜索效率,但是搜索二叉树会出现以...
      99+
      2022-11-13
    • Java中二叉树与N叉树的示例分析
      这篇文章主要介绍了Java中二叉树与N叉树的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。题目一 解法class Solution {&...
      99+
      2023-06-29
    • 镜像二叉树的示例分析
      镜像二叉树的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。算法这个东西很难,纵使你了解了其中的逻辑,用代码写出来仍然不是一件容易的事,内部有太多的细节需...
      99+
      2023-06-04
    • C语言树与二叉树基础全刨析
      目录一、树的概念和结构1.1 树的概念1.2 树的结构 & 相关名词解释1.3 树的表示1.4 树的应用二、二叉树的概念 & 存储结构(重要)2.1 二叉树的概念2....
      99+
      2022-11-13
    • C++二叉搜索树实例分析
      本篇内容介绍了“C++二叉搜索树实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!独一无二的二叉搜索树Given an integer&...
      99+
      2023-06-19
    • 【C++】平衡二叉搜索树的模拟实现
      🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风翻盘。 ...
      99+
      2023-09-11
      c++ 开发语言
    • C语言深入浅出解析二叉树
      目录树概念及结构相关概念树的表示树在实际中的运用(表示文件系统的目录树结构)二叉树概念及结构概念需要注意的特殊二叉树二叉树的性质二叉树的存储结构顺序存储链式存储总结树概念及结构 树是...
      99+
      2022-11-13
    • 如何使用C语言实现平衡二叉树数据结构算法
      目录前言一、平衡二叉树实现原理二、平衡二叉树实现算法三、全部代码前言 对于一个二叉排序树而言 它们的结构都是根据了二叉树的特性从最左子树开始在回到该结点上继续往右结点走 ...
      99+
      2022-11-12
    • web开发中二叉树的示例分析
      这篇文章将为大家详细讲解有关web开发中二叉树的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。0.  前言到目前为止,我们已经讲述了顺序表、链表、栈、队...
      99+
      2022-10-19
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作