【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

5.1 树的基本概念

5.1.1 树的定义

  • 一棵树是结点的有限集合T:
    • 若T非空,则:
      • 有一个特别标出的结点,称作该树的,记为root(T);
      • 其余结点分成若干个不相交的非空集合T1, T2, …, Tm (m>0),其中T1, T2, …, Tm又都是树,称作root(T)的子树
    • T 空时为空树,记作root(T)=NULL。

5.1.2 森林的定义

  一个森林是0棵或多棵不相交(非空)树的集合,通常是一个有序的集合。换句话说,森林由多个树组成,这些树之间没有交集,且可以按照一定的次序排列。在森林中,每棵树都是独立的,具有根节点和子树,树与树之间没有直接的连接关系。
  森林是树的扩展概念,它是由多个树组成的集合。在计算机科学中,森林也被广泛应用于数据结构和算法设计中,特别是在图论和网络分析等领域。
在这里插入图片描述

5.1.3 树的术语

  • 父亲(parent)、儿子(child)、兄弟(sibling)、后裔(descendant)、祖先(ancestor)
  • 度(degree)、叶子节点(leaf node)、分支节点(internal node)
  • 结点的层数
  • 路径、路径长度、结点的深度、树的深度

参照前文:【数据结构】树与二叉树(一):树(森林)的基本概念:父亲、儿子、兄弟、后裔、祖先、度、叶子结点、分支结点、结点的层数、路径、路径长度、结点的深度、树的深度

5.1.4 树的表示

  • 【数据结构】树与二叉树(二):树的表示C语言:树形表示法、嵌套集合表示法、嵌套括号表示法 、凹入表示法

5.2 二叉树

5.2.1 二叉树

1. 定义

  二叉树是一种常见的树状数据结构,它由结点的有限集合组成。一个二叉树要么是空集,被称为空二叉树,要么由一个根结点和两棵不相交的子树组成,分别称为左子树右子树。每个结点最多有两个子结点,分别称为左子结点和右子结点。
在这里插入图片描述

2. 特点

  二叉树的特点是每个结点最多有两个子结点,并且子结点的位置是有序的,即左子结点在前,右子结点在后。这种有序性使得二叉树在搜索、排序等算法中有广泛的应用。

  • 在二叉树中,根结点是整个树的起始点,通过根结点可以访问到整个树的其他结点。每个结点都可以看作是一个独立的二叉树,它的左子树和右子树也是二叉树。

  • 二叉树可以是空树,也可以是只有根结点的树,或者是由多个结点组成的树。每个结点可以包含一个数据元素,以及指向左子结点和右子结点的指针。

  • 二叉树的形状可以各不相同,它可以是平衡的或者不平衡的,具体取决于结点的分布情况。在二叉树中,每个结点的左子树和右子树都是二叉树,因此可以通过递归的方式来处理二叉树的操作。

3. 性质

引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i0
引理5.2:高度为k的二叉树中至多有 2 k + 1 − 1 2^{k+1}-1 2k+11个结点,其中 k ≥ 0 k \geq 0 k0
引理5.3:设T是由n个结点构成的二叉树,其中叶结点个数为 n 0 n_0 n0,度数为2的结点个数为 n 2 n_2 n2,则有 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1
  • 详细证明过程见前文:【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

4. 满二叉树

在这里插入图片描述

  定义5.3:一棵非空高度为 k ( k ≥ 0 ) k( k≥0) k(k0)满二叉树(perfect binary tree),是有 2 k + 1 − 1 2^{k+1}-1 2k+11个结点的二叉树。

5. 完全二叉树

  定义5.4:一棵包含 n n n个节点、高度为 k k k的二叉树 T T T,当按层次顺序编号 T T T的所有节点,对应于一棵高度为 k k k的满二叉树中编号由1至 n n n的那些节点时, T T T被称为完全二叉树(complete binary tree)

  • 满二叉树、完全二叉树性质及证明:【数据结构】树与二叉树(四):满二叉树、完全二叉树及其性质

5.2.2 二叉树顺序存储

  二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中
  对于完全二叉树,结点的层次顺序反映了其结构,可按层次顺序给出一棵完全二叉树之结点的编号,事实上,这就是完全二叉树的顺序存储方法,结点编号恰好反映了结点间的逻辑关系。
  只要对完全二叉树之结点按照层次顺序进行编号,就可利用一维数组 A A A来存储一棵含有 n n n个结点的完全二叉树,其中A[1]存储二叉树的根结点,A[i]存储二叉树中编号为i的结点,并且结点A[i]的左儿子(若存在)存放在A[2i]处,而A[i]的右儿子(若存在)存放在A[2i+1]处。注意,这里我们约定数组索引从1开始,而不是从0开始,在使用数组存储完全二叉树时,需要留出A[0]位置不使用。

典例

在这里插入图片描述

  首先,我们按照完全二叉树的结点顺序进行编号,从上到下、从左到右依次编号。根据给出的完全二叉树,我们可以得到以下结点编号:

         1
        / \
       2   3
      / \
     4   5

  接下来,我们可以利用一维数组来存储这棵完全二叉树。创建一个大小为6的数组A,其中A[1]表示根结点 A A AA[2]表示结点 B B BA[3]表示结点 E E EA[4]表示结点 C C CA[5]表示结点 D D D

索引:  1   2   3   4   5
数组: [ A,  B,  E,  C,  D ]

  根据完全二叉树的性质,结点 A A A的左儿子应该存放在A[2]的位置,右儿子应该存放在A[3]的位置。结点 B B B的左儿子应该存放在A[4]的位置,右儿子应该存放在A[5]的位置。

例题

  画出下面这棵完全二叉树的顺序存储结构:
在这里插入图片描述
答案见文末 答案见文末 答案见文末

  完全二叉树的顺序存储方式是一种简单且节省空间的存储方式。它只需要使用一个一维数组来存储完全二叉树的结点信息域的值,而不需要额外的空间来存储左儿子和右儿子的地址。

  通过计算结点的编号和数组索引之间的关系,我们可以方便地找到结点的左儿子、右儿子和父亲结点。例如,对于结点i,它的左儿子的编号是2i,右儿子的编号是2i+1,父亲结点的编号是⌊i/2⌋。这种计算关系使得寻找子孙结点和祖先结点变得非常方便和高效。

  顺序存储方式的优点是节省了存储空间,同时访问结点也非常快速,因为可以通过数组索引直接访问结点,而不需要进行指针的跳转。然而,顺序存储方式也有一些限制。由于使用数组存储,需要提前确定完全二叉树的最大结点个数,因此对于结点数不确定或者动态变化的情况下,顺序存储方式可能不适用。

C语言实现

  注意,这里我们约定数组索引从0开始,节点位置计算公式与前文略有不同。

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

#define MAX_SIZE 100  // 定义数组的最大大小

// 二叉树的顺序存储结构
typedef struct {
    char data[MAX_SIZE];  // 数组用于存储结点的数据
    int size;  // 二叉树的大小(结点个数)
} BinaryTree;

// 初始化二叉树
void initBinaryTree(BinaryTree* tree) {
    tree->size = 0;
}

// 向二叉树中插入结点
void insertNode(BinaryTree* tree, int value, int index) {
    if (tree->size >= MAX_SIZE) {
        printf("Binary tree is full. Cannot insert more nodes.\n");
        return;
    }

    if (index < 0 || index > tree->size) {
        printf("Invalid index.\n");
        return;
    }

    // 将插入位置后的结点后移
    for (int i = tree->size - 1; i >= index; i--) {
        tree->data[i + 1] = tree->data[i];
    }

    // 插入新结点
    tree->data[index] = value;
    tree->size++;
}

// 获取结点的父节点编号
int getParentIndex(int index) {
    return (index - 1) / 2;
}

// 获取结点的左子节点编号
int getLeftChildIndex(int index) {
    return 2 * index + 1;
}

// 获取结点的右子节点编号
int getRightChildIndex(int index) {
    return 2 * index + 2;
}

// 根据索引获取结点的值
char getNodeValue(BinaryTree* tree, int index) {
    if (index >= tree->size || index < 0) {
        printf("Invalid index.\n");
        return -1;
    }

    return tree->data[index];
}

int main() {
    BinaryTree tree;
    initBinaryTree(&tree);

    // 向二叉树中插入结点
    insertNode(&tree, 'A', 0);  
    insertNode(&tree, 'B', 1);  
    insertNode(&tree, 'E', 2); 
    insertNode(&tree, 'C', 3); 
    insertNode(&tree, 'D', 4); 

    // 获取结点的值和子节点的值
    char rootValue = getNodeValue(&tree, 0);
    char leftChildValue = getNodeValue(&tree, getLeftChildIndex(0));
    char rightChildValue = getNodeValue(&tree, getRightChildIndex(0));

    printf("Root value: %c\n", rootValue);
    printf("Left child of Root: %c\n", leftChildValue);
    printf("Right child of Root: %c\n", rightChildValue);

    printf("the Parent of B: %c\n", getNodeValue(&tree, getParentIndex(1)));
    printf("the Parent of C: %c\n", getNodeValue(&tree, getParentIndex(3)));
    printf("the Parent of D: %c\n", getNodeValue(&tree, getParentIndex(4)));
    printf("the Parent of E: %c\n", getNodeValue(&tree, getParentIndex(2)));
    return 0;
}

在这里插入图片描述

答案

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

10-27 maven概念

maven maven的概念模型: 项目对象模型(POM: Project object Model)&#xff0c;一组标准集合: pom.xml 依赖管理系统(Dependency Management System) 项目生命周期(Project Lifecycle) 项目对象模型&#xff1a; 把项目当成一个对象&#xff0c;描述这个项目&#xff0c;使用p…

【springboot配置项动态刷新】与【yaml文件转换为java对象】

文章目录 一&#xff0c;序言二&#xff0c;准备工作1. pom.xml引入组件2. 配置文件示例 三&#xff0c;自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四&#xff0c;yaml文件转换为java对象1. 无法使…

机器学习——逻辑回归

一、分类问题 监督学习的最主要类型 分类&#xff08;Classification&#xff09;&#xff1a; 身高1.85m&#xff0c;体重100kg的男人穿什么尺码的T恤&#xff1f;根据肿瘤的体积、患者的年龄来判断良性或恶性&#xff1f;根据用户的年龄、职业、存款数量来判断信用卡是否会…

Mac VsCode g++编译报错:不支持C++11语法解决

编译运行时报错&#xff1a; [Running] cd “/Users/yiran/Documents/vs_projects/c/” && g 1116.cpp -o 1116 && "/Users/yiran/Documents/vs_projects/c/"1116 1116.cpp:28:22: warning: range-based for loop is a C11 extension [-Wc11-extensi…

浅谈前端自定义VectorGrid矢量瓦片样式

目录 前言 一、VectorGrid相关API介绍 1、VectorGrid 2、 LayerStyles样式详解 二、样式自动配置 1、页面定义 2、地图及PBF瓦片引入 3、矢量瓦片样式定义 4、鼠标事件交互 三、最终效果 1、自定义样式展示 2、鼠标交互 总结 前言 在上一篇博客中&#xff0c;详细讲…

支付卡行业(PCI)PIN安全要求和测试程序 7个控制目标、33个要求及规范性附录ABC 密钥注入-PCI认证-安全行业基础篇4

概述 用于在ATM和POS终端进行在线和离线支付卡交易处理期间&#xff0c;对个人身份号码&#xff08;PIN&#xff09;数据进行安全管理、处理和传输。 该标准具体包括 7 个控制目标和 33 个安全要求&#xff0c; 标准的结构分为标准主体部分&#xff0c;标准附录&#xff08;N…

FPGA高端项目:图像缩放+GTP+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案我这里已有的图像处理方案 3、设计思路框架设计框图视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择…

C语言:深入浅出qsort方法,编写自己的qsort完成冒泡排序

目录 什么是qsort&#xff1f; 函数原型 比较函数 compar 排序整型数组 排序结构体数组 根据成员字符排序 strcmp函数 根据成员整型排序 自定义qsort实现冒泡排序 qsort的实现原理 具体步骤 快速排序示例代码&#xff1a; 什么是qsort&#xff1f; qsort是 C …

YOLO目标检测——交通标志分类数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;交通标志识别数据集在自动驾驶、交通安全监控、智能交通系统、驾驶员辅助系统和城市规划等领域都有广泛应用的潜力数据集说明&#xff1a;交通标志分类数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含多场景白天黑…

OOM排查

OOM排查 一&#xff0c;原因 1.一次性申请对象太多&#xff0c;创建了大量对象&#xff0c;尤其从表中读取了大量数据&#xff0c;循环中大量创建对象&#xff0c;放入list中。方案&#xff1a;限量 2.内存资源耗尽为释放&#xff0c;如connction&#xff0c;线程。方案&#…

猫罐头什么牌子好?2023营养又美味的猫主食罐头推荐!

亲爱的猫咪主人&#xff0c;你是否为你家小猫咪的挑食问题感到困扰&#xff1f;作为一位在宠物店工作了七年&#xff0c;负责喂养三十多只猫咪的店长&#xff0c;我对许多品牌的猫罐头都非常熟悉了。对于猫罐头哪个牌子好这个问题&#xff0c;我想借此机会分享一些见解。 在本…

软约束与硬约束

软约束硬约束 软约束硬约束 硬约束优化 1.基于走廊的光滑轨迹生成 2.基于贝塞尔曲线的轨迹优化 软约束优化 1.基于距离的轨迹优化 2.目标函数的设计 目标函数 光滑代价函数 碰撞代价函数 动力学代价函数。 光滑代价函数&#xff1a; 使用minimum snap来实现。 碰撞…

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别 介绍for循环参数ipairs和pairs whilerepeat until总结 介绍 这里我用while、for、repeat until分别输出1-20之间的奇数 &#xff0c;具体的语法可以看下面的代码 for循环 参数 定义一个初始值为start…

毫米波雷达技术的医疗创新:开启无创检测与监测的新时代

随着科技的不断进步&#xff0c;毫米波雷达技术正日益成为医疗领域的一项引人注目的创新。其无创性质、高分辨率和多功能性为医学诊断和监测带来了新的可能性。本文将深入探讨毫米波雷达技术在医疗创新中的应用&#xff0c;着眼于无创检测与监测领域的突破性发展。 1. 毫米波雷…

Babylonjs学习笔记(八)——网格行为

书接上回&#xff0c;这里讨论MeshAction网格行为&#xff01;&#xff01;&#xff01; 一、搭建基础场景 let box:AbstractMesh; let cube:AbstractMesh; let sphere:AbstractMesh; let cylinder:AbstractMesh; let mat:PBRMaterial;// 创建天空盒 const createSkyBox (sc…

如何在在线Excel文档中规范单元格输入

在日常的工作中&#xff0c;我们常常需要处理大量的数据。为了确保数据的准确性和可靠性。我们需要对输入的数据进行规范化和验证。其中一个重要的方面是规范单元格输入。而数据验证作为Excel中一种非常实用的功能&#xff0c;它可以帮助用户规范单元格的输入&#xff0c;从而提…

简单代理模式

代理模式 代理模式(Proxy)&#xff0c;为其他对象提供一种代理以控制对这个对象的访问。 结构图如下&#xff1a; ISubject接口&#xff0c;定义了RealSubject和Proxy的共用接口方法&#xff0c;这样就可以在任何使用RealSubject的地方使用Proxy代理。 ISubject接口 public…

JavaScript使用正则表达式

正则表达式(RegExp)也称规则表达式(regular expression)&#xff0c;是非常强大的字符串操作工具&#xff0c;语法格式为一组特殊字符构成的匹配模式&#xff0c;用来匹配字符串。ECMAScript 3以Perl为基础规范JavaScript正则表达式&#xff0c;实现Perl 5正则表达式的子集。Ja…

小米手机怎么识别图片上的表格文字?

前言&#xff1a; 小米手机怎么识别图片上的文字&#xff1f;有二种解决方案&#xff1a;一是直接用系统自带的OCR工具来实现&#xff0c;二是借助第三方软件&#xff08;如金鸣识别&#xff09;来实现。 一、用小米自带的系统工具来实现。 对于MIUI12.5以上系统的小米手机来…

学C++跟着视频学还是跟着书学?

学C跟着视频学还是跟着书学&#xff1f; 感觉得看基础和目标 如果不是喜欢 C 或者以求职 / 完成 C 相关工作为目标的话&#xff0c;菜鸟教程其实都够了&#xff0c;基本语法掌握就差不多&#xff0c;然后多去写。 最近很多小伙伴找我&#xff0c;说想要一些C的资料&#xff0…