【数据结构】树与二叉树(十六):二叉树的基础操作:插入结点(算法Insert)

文章目录

  • 5.2.1 二叉树
    • 二叉树性质
      • 引理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
    • 满二叉树、完全二叉树定义、特点及相关证明
  • 5.2.2 二叉树顺序存储
  • 5.2.3 二叉树链接存储
  • 5.2.4 二叉树的遍历
    • 1-3 先序、中序、后序遍历递归实现及相关练习
    • 4. 中序遍历非递归
    • 5. 后序遍历非递归
    • 6. 先序遍历非递归
    • 7. 层次遍历
  • 5.2.5 二叉树的创建
    • 1. 先序创建
    • 2. 复制二叉树
  • 5.2.6 二叉树的基础操作
    • 1. 查找给定结点的父亲
    • 2. 查找结点
    • 3. 插入结点
      • a. 算法InsertLL
      • b. InsertLeft
      • c. InsertRight
      • d. 算法测试
    • 4. 代码整合

5.2.1 二叉树

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

二叉树性质

引理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

  • 详细证明过程见前文:【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

满二叉树、完全二叉树定义、特点及相关证明

  • 详细证明过程见前文:【数据结构】树与二叉树(四):满二叉树、完全二叉树及其性质

5.2.2 二叉树顺序存储

  二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中,详见:
【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

5.2.3 二叉树链接存储

  二叉树的链接存储系指二叉树诸结点被随机存放在内存空间中,结点之间的关系用指针说明。在链式存储中,每个二叉树结点都包含三个域:数据域(Data)、左指针域(Left)和右指针域(Right),用于存储结点的信息和指向子结点的指针,详见:
【数据结构】树与二叉树(六):二叉树的链式存储

5.2.4 二叉树的遍历

  • 遍历(Traversal)是对二叉树中所有节点按照一定顺序进行访问的过程。
  • 通过遍历,可以访问树中的每个节点,并按照特定的顺序对它们进行处理。
  • 对二叉树的一次完整遍历,可给出树中结点的一种线性排序。
    • 在二叉树中,常用的遍历方式有三种:先序遍历中序遍历后序遍历
    • 这三种遍历方式都可以递归地进行,它们的区别在于节点的访问顺序
      • 在实现遍历算法时,需要考虑递归终止条件和递归调用的顺序。
    • 还可以使用迭代的方式来实现遍历算法,使用栈或队列等数据结构来辅助实现。
  • 遍历是二叉树中基础而重要的操作,它为其他许多操作提供了基础,如搜索、插入、删除等。
    在这里插入图片描述

1-3 先序、中序、后序遍历递归实现及相关练习

【数据结构】树与二叉树(七):二叉树的遍历(先序、中序、后序及其C语言实现)

4. 中序遍历非递归

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

5. 后序遍历非递归

【数据结构】树与二叉树(九):二叉树的后序遍历(非递归算法NPO)

6. 先序遍历非递归

【数据结构】树与二叉树(十):二叉树的先序遍历(非递归算法NPO)

7. 层次遍历

【数据结构】树与二叉树(十一):二叉树的层次遍历(算法LevelOrder)

5.2.5 二叉树的创建

1. 先序创建

  由二叉树的遍历,很容易想到用遍历方法去创建二叉树,我们考虑从先根遍历思想出发来构造二叉树:

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

2. 复制二叉树

  考虑用后根遍历思想递归复制二叉树的算法CopyTree:

【数据结构】树与二叉树(十三):递归复制二叉树(算法CopyTree)

5.2.6 二叉树的基础操作

1. 查找给定结点的父亲

  • 递归思想
    • 给定结点是指给定的是一个指向某个结点的指针(比如p)。
    • 返回值也应该是指针,指向结点p之父亲的指针(找不到时为空)。

【数据结构】树与二叉树(十四):二叉树的基础操作:查找给定结点的父亲(算法Father )

2. 查找结点

  考虑利用先根遍历在二叉树中搜索符合数据条件(item)的结点p,即满足data§=item的结点。

3. 插入结点

  在二叉树中插入结点,要确定待插入结点与插入位置结点的父子关系。设p为指向待插入结点的指针,简称结点p,s为指向插入位置结点的指针,简称结点s,即要确定p作为s的左儿子还是右儿子,以及如何维护s原来的父子关系。例如,指定p作为s的左儿子,s原来的左儿子作为p的左儿子,则:
在这里插入图片描述

a. 算法InsertLL

Insert

b. InsertLeft

void insertLeft(struct Node* p, struct Node* s) {if (s == NULL || p == NULL) {return;}p->left = s->left;s->left = p;
}
  • 如果s为空或者p为空,则返回
  • 将p的左儿子设置为s的左儿子
  • 将s的左儿子设置为p

c. InsertRight

void insertRight(struct Node* p, struct Node* s) {if (s == NULL || p == NULL) {return;}p->right = s->right;s->right = p;
}
  • 如果s为空或者p为空,则返回
  • 将p的右儿子设置为s的右儿子
  • 将s的右儿子设置为p

d. 算法测试

int main() {char tostop = '#';char input_data[] = {'a', 'b', 'd', '#', '#', 'e', 'f', '#', '#', 'g', '#', '#', 'c', '#', '#'};int index = 0;struct Node* root = CBT(input_data, &index, tostop);printf("Inorder Traversal before Insertion: ");inorderTraversal(root);printf("\n");struct Node* newNode = createNode('x');insertLeft(newNode, root);// insertRight(newNode, root);printf("Inorder Traversal after Insertion: ");inorderTraversal(root);printf("\n");releaseTree(root);root = NULL;return 0;
}
  • 采用前文算法CBT,先序递归创建一棵二叉树
  • 创建一个新的结点p,赋值x
  • 在二叉树中插入结点p,作为结点root的左儿子,原左儿子成为p的左儿子
  • 对比插入前后的结果
  • 释放整棵树
    • 注意,需要将释放的指针置为 NULL,以防止悬空指针。

4. 代码整合

#include <stdio.h>
#include <stdlib.h>// 二叉树结点的定义
struct Node {char data;struct Node* left;struct Node* right;
};// 创建新结点
struct Node* createNode(char data) {struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));if (newNode == NULL) {printf("Memory allocation failed!\n");exit(1);}newNode->data = data;newNode->left = NULL;newNode->right = NULL;return newNode;
}struct Node* CBT(char data[], int* index, char tostop) {char ch = data[(*index)++];if (ch == tostop) {return NULL;} else {struct Node* t = createNode(ch);t->left = CBT(data, index, tostop);t->right = CBT(data, index, tostop);return t;}
}// 释放以p指向结点为根的树
void releaseTree(struct Node* p) {// 如果p为空,则返回if (p == NULL) {return;}// 递归释放左子树releaseTree(p->left);// 递归释放右子树releaseTree(p->right);// 释放当前节点free(p);
}// 在二叉树中插入结点p,作为结点s的左儿子
void insertLeft(struct Node* p, struct Node* s) {// 如果s为空或者p为空,则返回if (s == NULL || p == NULL) {return;}// 将p的左儿子设置为s的左儿子p->left = s->left;// 将s的左儿子设置为ps->left = p;
}// 在二叉树中插入结点p,作为结点s的右儿子
void insertRight(struct Node* p, struct Node* s) {// 如果s为空或者p为空,则返回if (s == NULL || p == NULL) {return;}// 将p的右儿子设置为s的右儿子p->right = s->right;// 将s的右儿子设置为ps->right = p;
}void inorderTraversal(struct Node* root) {if (root != NULL) {inorderTraversal(root->left);printf("%c ", root->data);inorderTraversal(root->right);}
}int main() {// 创建一棵二叉树char tostop = '#';char input_data[] = {'a', 'b', 'd', '#', '#', 'e', 'f', '#', '#', 'g', '#', '#', 'c', '#', '#'};int index = 0;struct Node* root = CBT(input_data, &index, tostop);printf("Inorder Traversal before Insertion: ");inorderTraversal(root);printf("\n");// 创建一个新的结点pstruct Node* newNode = createNode('x');// 在二叉树中插入结点p,作为结点root的左儿子,原左儿子成为p的左儿子insertLeft(newNode, root);// insertRight(newNode, root);// 输出结果printf("Inorder Traversal after Insertion: ");inorderTraversal(root);printf("\n");// 释放整棵树releaseTree(root);// 注意,需要将释放的指针置为 NULL,以防止悬空指针。root = NULL;return 0;
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

通讯录实现之进阶版将通讯录数据保存在文件中(完整代码)

我们在之前的博客中已经写过两版通讯录了&#xff1a; 第一版是用C语言实现了通讯录&#xff0c;但是通讯录的存储人数信息是固定的&#xff0c;用完就没有了 感兴趣的可以转到对应博客看一下&#xff0c;附带链接&#xff1a;第一版通讯录 第二版是在第一版的基础上动态开辟…

三大开源向量数据库大比拼

向量数据库具有一系列广泛的好处&#xff0c;特别是在生成式人工智能方面&#xff0c;更具体地说&#xff0c;是在大语言模型&#xff08;LLM&#xff09;方面。这些好处包括先进的索引和精确的相似度搜索&#xff0c;有助于交付强大的先进项目。 本文将对三种开源向量数据库&…

“开源 vs. 闭源:大模型的未来发展趋势预测“——探讨大模型未来的发展方向

文章目录 每日一句正能量前言什么是大模型的开源与闭源开源与闭源的定义和特点开源的意义开源和闭源的优劣势比较不同的大模型企业&#xff0c;开源、闭源的策略不尽相同。企业在开发垂类模型时选择开源还是闭源大模型开源vs 闭源&#xff1a;两者并非选择题后记 每日一句正能量…

【网络】TCP协议的相关实验

TCP协议的相关实验 一、理解listen的第二个参数1、实验现象2、TCP 半连接队列和全连接队列3、关于listen的第二个参数的一些问题4、SYN洪水Ⅰ、什么是SYN洪水攻击Ⅱ、如何解决SYN洪水攻击&#xff1f; 二、使用Wireshark分析TCP通信流程 一、理解listen的第二个参数 在编写TCP…

有什么进销存软件,比较适合零售行业日常开单要求及库存记录?

本文将为大家总结一下对于进销存软件要求&#xff1a; 基础功能&#xff1a;可以日常开单、退换货处理、出入库进阶功能&#xff1a;电脑、手机数据同步&#xff0c;保障数据安全&#xff0c;可进行数据分析 其实无论是小型创业公司&#xff0c;还是一家大型企业&#xff0c;…

MathType2024最新word公式编辑器

使用word进行论文编写时&#xff0c;常需要使用公式编辑器&#xff0c;但有些word中并没有公式编辑器&#xff0c;这时应该怎么办呢&#xff1f;本文将围绕word里没有公式编辑器怎么办&#xff0c;word中的公式编辑器怎么用的内容进行介绍。 一、word里没有公式编辑器怎么办 …

现货黄金职业交易员怎么使用技术分析?

职业的交易员每天要处理很多不同的信息&#xff0c;其中只一部分是涉及技术指标。在这一部分处理技术分析的时间里&#xff0c;只能再分出少之又少的时间给技术指标。那职业交易员会利用做技术指标做什么呢&#xff1f;下面我们就来讨论一下。 识别行情。技术指标的主要作用就是…

Digicert证书:您的网络安全守护神

在当今数字化的世界中&#xff0c;网络安全已经成为每一个企业和个人必须面对的问题。而Digicert品牌证书&#xff0c;就是您网络安全的最佳选择。它不仅具有强大的安全性和稳定性&#xff0c;还能广泛应用于各种场景&#xff0c;为您提供全方位的保护。 首先&#xff0c;我们要…

【Linux】Ubuntu16.04配置repo

Ubuntu16.04配置repo失败 在学习韦东山Linux嵌入式开发过程中&#xff0c;使用repo获取内核及工具链: git clone https://e.coding.net/codebug8/repo.gitmkdir -p 100ask_imx6ull-sdk && cd 100ask_imx6ull-sdk../repo/repo init -u https://gitee.com/weidongshan/m…

万能在线答题考试小程序源码系统 既能刷题 又能考试 带完整的搭建教程

现如今&#xff0c;线上学习和考试已经成为一种趋势。近年来&#xff0c;移动端的普及以及微信小程序的兴起&#xff0c;使得在线答题考试系统变得更加便捷和高效。今天罗峰就来给大家介绍一款万能在线答题考试小程序源码系统&#xff0c;既能刷题&#xff0c;又能考试&#xf…

Tosca 2023x 新功能介绍

Tosca/Structure的功能增强 热优化功能增强 在优化过程中&#xff0c;支持将对流边界条件转移至新创建的表面&#xff0c;方便更加真实地模拟传热行为。支持恒定传导。多物理场优化能力增强。通过使用多个输入面板对热和结构荷载进行分别输入&#xff0c;以支持同时对热和结构…

​软考-高级-系统架构设计师教程(清华第2版)【第10章 软件架构的演化和维护(P345~382)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第10章 软件架构的演化和维护&#xff08;P345~382&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

【k8s集群搭建(二):基于虚拟机的linux的k8s集群搭建_超详细_可视化界面Dashboard安装_记录全过程踩坑记录及解决方法】

在 master 执行 # 根据 在线配置文件 创建资源 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml设置访问端口 # 修改配置文件 找到 type&#xff0c;将 ClusterIP 改成 NodePort kubectl edit svc kubernetes-…

2023年中国冲击波治疗仪市场发展趋势分析:未来市场增长空间更大[图]

冲击波在临床医学领域最早应用于体外冲击波碎石&#xff0c;在二十世纪八十年代末期&#xff0c;体外冲击波碎石技术开始被运用到骨科及康复理疗领域&#xff0c;经过十余年的临床研究&#xff0c;冲击波疗法日益完善&#xff0c;应用范围也日益扩大。冲击波作为一种介于保守疗…

【入门篇】1.7 Redis 之 codis 入门介绍

文章目录 1. 简介2. Codis的安装与配置下载编译源码安装1. 安装 Go 运行环境2. 设置编译环境3. 下载 Codis 源代码4. 编译 Codis 源代码 Docker 部署 3. Codis的架构Codis的架构图和组件Codis的工作流程 4. Codis的核心特性自动数据分片数据迁移高可用性全面支持Redis命令分布式…

【fbtft】如何添加fbtft驱动

获取lcd ic的datasheet&#xff0c;或者直接找到其他平台&#xff08;linux&#xff0c;stm32&#xff0c;esp32&#xff09;的驱动 我用的是合宙的esp32驱动&#xff0c;注意是c语言的&#xff0c;合宙上层用lua封装了&#xff0c;需要找到sdk源码。 源码路径&#xff1a; …

File类和IO流

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

设置chunk自动扩展到多大

1. 设置chunk自动扩展 execute function task(modify chunk extendable on,8); 2. 设置dbs扩展到多大合适 execute function task(modify space sp sizes,testdb1024,1024,10240) testdb 初始1MB 下次扩1MB 最大10MB

appium+python自动化测试

获取APP的包名 1、aapt即Android Asset Packaging Tool&#xff0c;在SDK的build-tools目录下。该工具可以查看apk包名和launcherActivity 2、在android-sdk里面双击SDK-manager,下载buidl-tools 3、勾选build-tools&#xff0c;随便选一个版本&#xff0c;我这里选的是24的版…

宏集干货 | 手把手教你通过CODESYS V3进行PLC编程(三)

来源&#xff1a;宏集科技 工业物联网 宏集干货 | 手把手教你通过CODESYS V3进行PLC编程&#xff08;三&#xff09; 教程背景 通过之前的教程&#xff0c;我们已经为大家演示了宏集MC-Prime控制器的连接、试运行和CODESYS的安装&#xff0c;并创建了一个计数器项目。在本期教…