数据结构之二叉树详解:从原理到实现

1. 什么是二叉树?

二叉树(Binary Tree)是一种树形数据结构,其中每个节点最多有两个子节点,分别被称为左子节点右子节点。二叉树可以用来表示层次关系,如文件目录组织结构,或用于快速查找、排序和决策问题。其结构如下:

2. 二叉树的基本术语

在了解二叉树之前,我们需要掌握一些关键术语:

  • 节点(Node):二叉树的基本单元,包含数据和指向子节点的指针。
  • 根节点(Root):二叉树的最顶端节点。
  • 叶子节点(Leaf):没有子节点的节点。
  • 高度(Height):从某节点到叶子节点的最长路径上的边数。
  • 深度(Depth):从根节点到某节点所经过的边数。
  • 子树(Subtree):由某节点及其子节点组成的部分树。

3. 二叉树的分类

根据节点的分布特点,二叉树有多种类型:

  1. 满二叉树:每个节点都有两个子节点,且所有叶子节点在同一层。
  2. 完全二叉树:除了最后一层外,其他层的节点都被填满,最后一层的叶子节点从左到右连续排列。
  3. 二叉搜索树(BST):对于任意一个节点,左子树中的所有节点值都小于该节点值,右子树中的所有节点值都大于该节点值。
  4. 平衡二叉树:左右子树的高度差不超过1。
4. 二叉树的存储结构
二叉树可以通过两种方式存储:
  1. 链式存储:用链表表示,每个节点包含数据和左右子节点的指针。
  2. 顺序存储:用数组表示,通常用于完全二叉树或满二叉树。
链式存储

在C语言中,链式存储通常使用结构体来定义二叉树节点:

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

// 定义二叉树节点
struct TreeNode {
    int data;                // 数据域
    struct TreeNode* left;   // 左子节点指针
    struct TreeNode* right;  // 右子节点指针
};

// 创建新节点
struct TreeNode* createNode(int data) {
    struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

​
顺序存储

顺序存储常用数组表示,用于完整或接近完整的二叉树。节点的存储规则如下:

  • 根节点存储在索引1(或0)。
  • 索引为i的节点的左子节点在2*i位置,右子节点在2*i+1位置。
  • 父节点在索引i/2位置。
5. 二叉树的基本操作
1. 插入节点

插入节点的方式取决于二叉树的类型。在二叉搜索树(BST)中,插入节点时需要保持左小右大的规则。

​
struct TreeNode* insert(struct TreeNode* root, int data) {
    if (root == NULL) {
        return createNode(data);  // 如果当前节点为空,创建新节点
    }
    if (data < root->data) {
        root->left = insert(root->left, data);  // 插入左子树
    } else if (data > root->data) {
        root->right = insert(root->right, data); // 插入右子树
    }
    return root;
}

​
2. 查找节点

在二叉搜索树中查找节点时,可以利用其有序性快速定位目标节点。

​
struct TreeNode* search(struct TreeNode* root, int key) {
    if (root == NULL || root->data == key) {
        return root;  // 找到节点或到达空节点
    }
    if (key < root->data) {
        return search(root->left, key);  // 在左子树中查找
    } else {
        return search(root->right, key); // 在右子树中查找
    }
}

​
3. 遍历二叉树

二叉树的遍历方式分为以下几种:

  • 前序遍历(Pre-order):根节点 -> 左子树 -> 右子树
  • 中序遍历(In-order):左子树 -> 根节点 -> 右子树
  • 后序遍历(Post-order):左子树 -> 右子树 -> 根节点
  • 层序遍历(Level-order):按层次从上到下逐层遍历
前序遍历
​
void preOrder(struct TreeNode* root) {
    if (root == NULL) return;
    printf("%d ", root->data);
    preOrder(root->left);
    preOrder(root->right);
}

​
中序遍历
​
void inOrder(struct TreeNode* root) {
    if (root == NULL) return;
    inOrder(root->left);
    printf("%d ", root->data);
    inOrder(root->right);
}

​
后序遍历
​
void postOrder(struct TreeNode* root) {
    if (root == NULL) return;
    postOrder(root->left);
    postOrder(root->right);
    printf("%d ", root->data);
}

​
4. 删除节点

在二叉搜索树中删除节点我们需要考虑三种情况

  1. 被删除节点是叶子节点。
  2. 被删除节点有一个子节点。
  3. 被删除节点有两个子节点。
​
struct TreeNode* deleteNode(struct TreeNode* root, int key) {
    if (root == NULL) return root;

    if (key < root->data) {
        root->left = deleteNode(root->left, key);  // 在左子树中删除
    } else if (key > root->data) {
        root->right = deleteNode(root->right, key); // 在右子树中删除
    } else {
        // 找到要删除的节点
        if (root->left == NULL) {
            struct TreeNode* temp = root->right;
            free(root);
            return temp;
        } else if (root->right == NULL) {
            struct TreeNode* temp = root->left;
            free(root);
            return temp;
        }
        // 有两个子节点,找右子树的最小节点
        struct TreeNode* temp = root->right;
        while (temp->left != NULL) {
            temp = temp->left;
        }
        root->data = temp->data; // 用最小值替换当前节点
        root->right = deleteNode(root->right, temp->data); // 删除最小节点
    }
    return root;
}

​
6. 二叉树的应用
  1. 二叉搜索树(BST):用于快速查找、插入和删除操作。
  2. 堆(Heap):用于优先队列和排序。
  3. 表达式树:用于表示算术表达式。
  4. Huffman树:用于数据压缩。
  5. 平衡二叉树(AVL/红黑树):用于高效的动态数据结构

表示文件系统的目录树结构

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)

附件 calculate.html <!DOCTYPE html> <html lang"en"> <head><!-- 设置字符编码为 UTF-8&#xff0c;支持多语言字符集 --><meta charset"UTF-8"><!-- 设置响应式视图&#xff0c;确保页面在不同设备上自适应显示 --&…

用于LiDAR测量的1.58um单芯片MOPA(一)

--翻译自M. Faugeron、M. Krakowski1等人2014年的文章 1.简介 如今&#xff0c;人们对高功率半导体器件的兴趣日益浓厚&#xff0c;这些器件主要用于遥测、激光雷达系统或自由空间通信等应用。与固态激光器相比&#xff0c;半导体器件更紧凑且功耗更低&#xff0c;这在低功率供…

【maven-5】Maven 项目构建的生命周期:深入理解与应用

1. 生命周期是什么 ​在Maven出现之前&#xff0c;项目构建的生命周期就已经存在&#xff0c;软件开发人员每天都在对项目进行清理&#xff0c;编译&#xff0c;测试及部署。虽然大家都在不停地做构建工作&#xff0c;但公司和公司间&#xff0c;项目和项目间&#xff0c;往往…

数字时代的文化宝库:存储技术与精神生活

文章目录 1. 文学经典的数字传承2. 音乐的无限可能3. 影视艺术的数字化存储4. 结语 数字时代的文化宝库&#xff1a;存储技术与精神生活 在数字化的浪潮中&#xff0c;存储技术如同一座桥梁&#xff0c;连接着过去与未来&#xff0c;承载着人类文明的瑰宝。随着存储容量的不断增…

STM32标准库-FLASH

FLASH模仿EEPROM STM32本身没有自带EEPROM&#xff0c;但是自带了FLASH存储器。 STM32F103ZET6自带 1M字节的FLASH空间&#xff0c;和 128K64K的SRAM空间。 STM32F4 的 SPI 功能很强大&#xff0c;SPI 时钟最高可以到 37.5Mhz&#xff0c;支持 DMA&#xff0c;可以配置为 SPI协…

重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)

在平常的学习和工作中&#xff0c;我们创建对象一般会直接用new&#xff0c;但是很多时候直接new会存在一些问题&#xff0c;而且直接new会让我们的代码变得非常繁杂&#xff0c;这时候就会巧妙的用到设计模式&#xff0c;平常我们通过力扣学习的算法可能并不会在我们工作中用到…

linux(centos) 环境部署,安装JDK,docker(mysql, redis,nginx,minio,nacos)

目录 1.安装JDK (非docker)1.1 将文件放在目录下&#xff1a; /usr/local/jdk1.2 解压至当前目录1.3 配置环境变量 2.安装docker2.1 验证centos内核2.2 安装软件工具包2.3 设置yum源2.4 查看仓库中所有docker版本&#xff0c;按需选择安装2.5 安装docker2.6 启动docker 并 开机…

算法日记 40 day 单调栈

最后两题了&#xff0c;直接上题目。 题目&#xff1a;接雨水 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1…

yagmail邮件发送库:如何用Python实现自动化邮件营销?

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

【RL Base】强化学习:信赖域策略优化(TRPO)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

黑马2024AI+JavaWeb开发入门Day04-SpringBootWeb入门-HTTP协议-分层解耦-IOCDI飞书作业

视频地址&#xff1a;哔哩哔哩 讲义作业飞书地址&#xff1a;day04作业&#xff08;IOC&DI&#xff09; 作业很简单&#xff0c;主要是练习拆分为三层架构controller、service、dao&#xff0c;并基于IOC & DI进行解耦。 1、结构&#xff1a; 2、代码 网盘链接&…

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!)

目录 实验三 学校选址与道路规划 3.1 实验内容及目的 3.1.1 实验内容 3.1.2 实验目的 3.2 实验方案 3.3 操作流程 3.3.1 环境设置 3.3.2 地势分析 &#xff08;1&#xff09;提取坡度: (2)重分类: 3.3.3 学校点分析 (1)欧氏距离: (2)重分类: 3.3.4 娱乐场所点分析 (1)欧氏距离…

【Python网络爬虫笔记】8- (BeautifulSoup)抓取电影天堂2024年最新电影,并保存所有电影名称和链接

目录 一. BeautifulSoup的作用二. 核心方法介绍2.1 构造函数2.2 find()方法2.3 find_all()方法2.4 select()方法 三. 网络爬虫中使用BeautifulSoup四、案例爬取结果 一. BeautifulSoup的作用 解析HTML/XML文档&#xff1a;它可以将复杂的HTML或XML文本转换为易于操作的树形结构…

MATLAB期末复习笔记(中)

目录 三、MATLAB函数和程序结构 1.MATLAB文件 2.变量和数据类型 &#xff08;1&#xff09;变量 &#xff08;2&#xff09;变量类型 &#xff08;3&#xff09;字符串 3.函数文件 &#xff08;1&#xff09;函数文件规范 &#xff08;2&#xff09;子函数和私有函数 &…

算法刷题Day8:BM30 二叉搜索树与双向链表

题目 牛客网题目传送门 思路 对二叉搜索树进行中序遍历&#xff0c;结果就是按序数组。因此想办法把前面遍历过的节点给记下来&#xff0c;记作pre。当遍历到某个节点node的时候&#xff0c;令前驱指向pre&#xff0c;然后让pre的后驱指向node。 代码 class TreeNode:def…

深入解析 Dubbo 中的常见问题及优化方案: 数据量限制与配置错误20241203

&#x1f31f; 深入解析 Dubbo 中的常见问题及优化方案&#xff1a;数据量限制与配置错误 在分布式系统中&#xff0c;Dubbo 作为高性能的 RPC 框架广泛应用于企业服务化架构。然而&#xff0c;在实际使用过程中&#xff0c;开发者往往会遇到一些复杂问题&#xff0c;比如 数据…

debian ubuntu armbian部署asp.net core 项目 开机自启动

我本地的环境是 rk3399机器&#xff0c;安装armbian系统。 1.安装.net core 组件 sudo apt-get update && \sudo apt-get install -y dotnet-sdk-8.0或者安装运行库&#xff0c;但无法生成编译项目 sudo apt-get update && \sudo apt-get install -y aspnet…

【AI系统】Ascend C 编程范式

Ascend C 编程范式 AI 的发展日新月异&#xff0c;AI 系统相关软件的更新迭代也是应接不暇&#xff0c;作为一本讲授理论的作品&#xff0c;我们将尽可能地讨论编程范式背后的原理和思考&#xff0c;而少体现代码实现&#xff0c;以期让读者理解 Ascend C 为何这样设计&#x…

hadoop环境配置-创建hadoop用户+更新apt+安装SSH+配置Java环境

一、创建hadoop用户(在vm安装的ubantu上打开控制台) 1、sudo useradd -m hadoop -s /bin/bash &#xff08;创建hadoop用户&#xff09; 2、sudo passwd hadoop (设置密码) 3、sudo adduser hadoop sudo&#xff08;将新建的hadoop用户设置为管理员&#xff09; 执行如下图 将…

嵌入式系统应用-LVGL的应用-平衡球游戏 part1

平衡球游戏 part1 1 平衡球游戏的界面设计2 界面设计2.1 背景设计2.2 球的设计2.3 移动球的坐标2.4 用鼠标移动这个球2.5 增加边框规则2.6 效果图 3 为小球增加增加动画效果3.1 增加移动效果代码3.2 具体效果图片 平衡球游戏 part2 第二部分文章在这里 1 平衡球游戏的界面设计…