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

news2024/9/20 20:50:07

平衡二叉树(Balanced Binary Tree)是一种特殊的二叉树,它的左右子树的高度差不超过1,这样可以保证树的高度相对较低,从而使得查找、插入和删除操作的时间复杂度保持在 O\left ( \log n \right )

平衡二叉树的基本概念

1. 二叉树:每个节点最多有两个子节点,分别称为左子节点和右子节点。
2. 平衡条件:对于每个节点,左子树和右子树的高度差的绝对值不超过1。
3. 高度:树的高度是从根节点到最深叶子节点的最长路径上的边的数量。

 AVL树

AVL树是最早的自平衡二叉查找树,由G.M. Adelson-Velsky和E.M. Landis在1962年提出。AVL树通过在每个节点存储一个平衡因子(左子树高度减去右子树高度)来保持平衡。

AVL树的基本操作

1. 插入:插入新节点后,检查树的平衡情况,必要时进行旋转操作以保持平衡。
2. 删除:删除节点后,同样检查树的平衡情况,并进行旋转操作。
3. 旋转:包括左旋、右旋、左右旋和右左旋四种操作,用于调整树的结构。

AVL树的实现

下面是一个简单的AVL树实现,包括插入和旋转操作的示例代码:

#include <stdio.h>
#include <stdlib.h>

// AVL树节点结构
typedef struct Node {
    int key;
    int height; // 节点的高度
    struct Node* left;
    struct Node* right;
} Node;

// 获取节点的高度
int height(Node* N) {
    if (N == NULL)
        return 0;
    return N->height;
}

// 获取平衡因子
int getBalance(Node* N) {
    if (N == NULL)
        return 0;
    return height(N->left) - height(N->right);
}

// 创建新节点
Node* newNode(int key) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->key = key;
    node->left = NULL;
    node->right = NULL;
    node->height = 1; // 新节点的高度为1
    return node;
}

// 右旋转
Node* rightRotate(Node* y) {
    Node* x = y->left;
    Node* T2 = x->right;

    // 进行旋转
    x->right = y;
    y->left = T2;

    // 更新高度
    y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));
    x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));

    return x; // 返回新的根节点
}

// 左旋转
Node* leftRotate(Node* x) {
    Node* y = x->right;
    Node* T2 = y->left;

    // 进行旋转
    y->left = x;
    x->right = T2;

    // 更新高度
    x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));
    y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));

    return y; // 返回新的根节点
}

// 插入节点
Node* insert(Node* node, int key) {
    // 1. 执行常规的BST插入
    if (node == NULL)
        return newNode(key);

    if (key < node->key)
        node->left = insert(node->left, key);
    else if (key > node->key)
        node->right = insert(node->right, key);
    else // 不允许重复的键
        return node;

    // 2. 更新节点的高度
    node->height = 1 + (height(node->left) > height(node->right) ? height(node->left) : height(node->right));

    // 3. 检查平衡性
    int balance = getBalance(node);

    // 如果不平衡,有四种情况

    // 左左情况
    if (balance > 1 && key < node->left->key)
        return rightRotate(node);

    // 右右情况
    if (balance < -1 && key > node->right->key)
        return leftRotate(node);

    // 左右情况
    if (balance > 1 && key > node->left->key) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    // 右左情况
    if (balance < -1 && key < node->right->key) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    // 返回(未改变的)节点指针
    return node;
}

// 中序遍历
void inorder(Node* root) {
    if (root != NULL) {
        inorder(root->left);
        printf("%d ", root->key);
        inorder(root->right);
    }
}

int main() {
    Node* root = NULL;

    // 插入节点
    root = insert(root, 10);
    root = insert(root, 20);
    root = insert(root, 30);
    root = insert(root, 40);
    root = insert(root, 50);
    root = insert(root, 25);

    // 中序遍历
    printf("中序遍历AVL树:");
    inorder(root);
    printf("\n");

    return 0;
}

代码说明

1. 节点结构:`Node`结构体包含键值、节点高度和左右子节点的指针。
2. 高度和平衡因子的计算:`height`和`getBalance`函数用于计算节点的高度和获取平衡因子。
3. 旋转操作:`rightRotate`和`leftRotate`函数用于进行树的旋转,以保持平衡。
4. 插入操作:`insert`函数用于插入新节点并保持AVL树的平衡。
5. 中序遍历:`inorder`函数用于遍历树并输出节点的键值。

AVL树是一种自平衡的二叉查找树,能够在插入和删除操作后保持平衡,从而保证高效的查找性能。通过旋转操作,AVL树能够在动态数据集上保持良好的性能。以上代码展示了AVL树的基本实现,可以根据需要进行扩展和优化。

觉得有帮助的话点个赞吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1987060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 热题 HOT 100 (020/100)【宇宙最简单版】[创作中]

【链表】No. 0142 环形链表 II【中等】&#x1f449;力扣对应题目指路 希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【力扣详解】谢谢你的支持&#…

C++ 简单学习

C简单编译 auto关键字 auto 关键字用于自动类型推导。它允许编译器自动推断变量的类型&#xff0c;使得代码更加简洁和易于编写&#xff0c;尤其是在处理复杂类型或模板编程时。使用 auto 可以避免编写冗长的类型声明&#xff0c;同时减少由于类型不匹配导致的编译错误 auto x…

学习vue3 三,组件基础,父子组件传值

组件基础 每一个.vue 文件都可以充当组件来使用 每一个组件都可以复用 父组件引入之后可以直接当标签使用 案例&#xff1a; App.vue <script setup lang"ts"> import BaseRefAndReactive from "./components/BaseRefAndReactive.vue";</sc…

Docker部署Node+Koa+TS+Mongo项目

Docker 简介 简而言之&#xff0c;Docker 容器轻量级、启动快、可移植&#xff0c;适合微服务架构。主要组件包括 Docker Engine、Docker 镜像、Docker 容器和 Docker Hub&#xff0c;它通过容器打包应用程序及其依赖项&#xff0c;使得应用在任何环境中都能一致运行。 这里不…

Selenium中send_keys上传图片方法以及可能失败的原因

Python Selenium是一个用于自动化浏览器操作的工具&#xff0c;可以用于模拟用户在浏览器中的各种操作。在使用Python Selenium进行自动化测试时&#xff0c;有时需要上传图片。下面是在这种情况下如何上传图片的步骤&#xff1a; 今天是主要说的是input标签&#xff0c;这种可…

基于R语言绘制GGE双标图3

参考资料&#xff1a; https://cran.r-project.org/web/packages/GGEBiplots/GGEBiplots.pdf GGE叠图法一分析品种环境互作模式的理想方法【作物学报】 GGE 双标图如何看&#xff1f;-CSDN博客 1、品种间两两比较 GGE 双标图可用于直接比较两个品种在各个试验点的表现&…

白银市场暴跌的技术分析与投资策略

一、白银市场暴跌与技术分析 周一&#xff08;8月5日&#xff09;&#xff0c;现货白银暴跌逾4.5%&#xff0c;并跌破关键的100日移动均线。FXStreet分析师Christian Borjon Valencia对银价技术走势进行了分析&#xff0c;指出银价前景转为看跌&#xff0c;技术面显示白银将进一…

探索Python并发的秘境:Greenlet库的奇幻之旅

文章目录 探索Python并发的秘境&#xff1a;Greenlet库的奇幻之旅背景&#xff1a;为何选择Greenlet&#xff1f;绿野仙踪&#xff1a;Greenlet是什么&#xff1f;安装&#xff1a;如何将Greenlet纳入囊中&#xff1f;功能探索&#xff1a;Greenlet的五大法宝场景应用&#xff…

【系统分析师】-综合知识-软件工程与项目管理

1、按照成本性态分类&#xff0c;可以分为固定成本、变动成本和混合成本。 &#xff08;1&#xff09;固定成本。管理人员的工资、办公费、固定资产折旧费、员工培训费、广告费、员工培训费、技术开发经费、办公场地及机器设备的折旧费、房屋及设备租金、管理人员的工资等。 …

提示工程:CO-STAR框架

在人工智能领域&#xff0c;尤其是大型语言模型&#xff08;LLM&#xff09;的应用中&#xff0c;提示工程已成为一项至关重要的技能。它不仅需要对技术有深刻的理解&#xff0c;还需要创造力和战略思维的结合。本文将探讨提示工程的重要性&#xff0c;详细介绍CO-STAR框架的使…

0209-开发状态切换(场景切换)功能

一、设置场景状态 1、已有方法 2、实现步骤 引用API&#xff1a;using UnityEngine.SceneManagement 写设置场景状态的方法 场景名字切换&#xff0c;需要获取mSceneName&#xff0c;他是私有的&#xff0c;给一个getset 3、问题 &#xff08;1&#xff09;同步加载 加载场…

【Web开发手礼】探索Web开发的秘密(十六)-Vue2(2)前端工程化、Element组件表格、分页

主要介绍了前端工程化Vue的开发流程、Element组件介绍以及常见的Element组件表格、分页&#xff01;&#xff01;&#xff01; 目录 前言 前端工程化 Vue项目-创建 Vue项目-目录结构 Vue项目-启动 Vue项目-配置端口 Vue项目开发流程 Element组件 快速入门 常见组件 表格…

2024杭电多校(4) 1008. 树形DNA【01Trie、哈希】

题意 给定两颗二叉树 S S S 和 T T T&#xff0c;如果对于 S S S 的某个子树 S ′ S^\prime S′&#xff0c;删除若干个&#xff08;或不删除&#xff09;其子树后&#xff0c;可以和 T T T 相同&#xff08;左子树与左子树匹配&#xff0c;右子树与右子树匹配&#xff0…

C++入门基础知识

在之前我们学习了C语言和初阶数据结构的相关知识&#xff0c;现在已经有了一定的代码能力和对数据结构也有了基础的认识&#xff0c;接下来我们将进入到新的专题当中&#xff0c;这个专题就是C。在C中我们需要花费更大的精力和更长的时间去学习这门建立在C语言基础之上的计算机…

新一代AI软件基础设施 | ZStack AIOS平台“智塔”发布

新一代 IT 基础设施&#xff0c;将从通用算力云平台转型为AI算力AIOS平台。 AI正在重构世界。正如世界是立体的&#xff0c;AI重构也正从多维度开启&#xff1a;基础设施重构&#xff0c;业务应用重构&#xff0c;交互模式重构&#xff0c;数据价值重构&#xff0c;生态系统重…

移动IP:让你的设备随时随地保持连接

随着无线网络技术的迅猛发展&#xff0c;在移动中进行数据通信已成为可能。成千上万的人正在使用移动设备畅享互联网&#xff0c;无论是在火车上、汽车内&#xff0c;还是在其他移动场景中。本文将带你了解移动IP&#xff08;Mobile IP&#xff09;的工作原理及其对网络应用的影…

LLM在线理解;神将网络理解;transform架构

目录 LLM在线理解 神将网络理解 transform架构 模型的子结构: 三个计算 计算1 计算2 计算3 LLM在线理解 LLM Visualization 神将网络理解 transform架构 模型的子结构: 词向量(Embedding) 前馈神经网络(Feed Forward) 残差连接(Add)和层标准化(Norm) 线性层(Linear…

Python版本和cuda版本不匹配解决办法

一、检查版本是否匹配 使用Python进入控制台&#xff0c;然后执行&#xff1a; >>>print(torch.cuda.is_available())如果输出为 False&#xff0c;则说明不匹配 退出Python环境&#xff0c;再检查系统版本&#xff1a; exit()nvcc -V 二、安装 去官网 PyTorch …

转载一篇关于对Linux磁盘部分mount和挂载的解释

转载自: http://t.csdnimg.cn/V3lgahttp://t.csdnimg.cn/V3lga

3_stm32_pwm呼吸灯

到目前已经可以进行基础的Led亮灭控制、使用定时器中断控制Led的亮灭。但是发现Led只有“亮”和 “灭”两种状态&#xff0c;那是否可以有更多状态&#xff1f;如何有更多状态呢&#xff1f;更进一步的想法&#xff0c;Led亮是有了电压差&#xff0c;其中一端是地&#xff0c;那…