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

news2025/1/11 22:43:09

文章目录

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之父亲的指针(找不到时为空)。

a. 算法Father

在这里插入图片描述

b. 时间复杂度

  在递归实现的二叉树查找父亲的算法中,每个节点都要进行一次判断,最坏情况下,每个节点都需要被访问一次,所以时间复杂度是 O(n),其中 n 是二叉树的节点数。
  三叉链表是二叉树的一种存储结构,其中每个节点包含指向其左孩子、右孩子和父亲节点的指针。这种存储结构确实提供了在 O(1) 时间内访问父亲节点的能力。但请注意,这样的存储结构会占用更多的空间,因为每个节点需要额外的指针来存储父亲节点的地址。

  • 选择使用哪种存储结构通常取决于对时间和空间的权衡。
    • 如果空间要求比较敏感,并且不需要频繁访问父亲节点,那么递归实现可能是一个合理的选择。
    • 如果你需要高效地进行父亲节点的访问,并且可以接受更多的空间开销,那么三叉链表可能更适合。

c. 代码实现

struct Node* findFather(struct Node* root, struct Node* p) {
    // 如果树为空或者给定结点为空,则返回NULL
    if (root == NULL || p == NULL) {
        return NULL;
    }

    // 如果给定结点是根节点,则根据定义返回NULL
    if (root == p) {
        return NULL;
    }

    // 如果给定结点是根节点的左孩子或右孩子,则根节点就是其父亲
    if (root->left == p || root->right == p) {
        return root;
    }

    // 在左子树中递归查找
    struct Node* leftResult = findFather(root->left, p);
    if (leftResult != NULL) {
        return leftResult;
    }

    // 在右子树中递归查找
    return findFather(root->right, p);
}

2. 代码整合

#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;
    }
}

// 查找给定结点的父亲节点(递归实现)
struct Node* findFather(struct Node* root, struct Node* p) {
    // 如果树为空或者给定结点为空,则返回NULL
    if (root == NULL || p == NULL) {
        return NULL;
    }

    // 如果给定结点是根节点,则根据定义返回NULL
    if (root == p) {
        return NULL;
    }

    // 如果给定结点是根节点的左孩子或右孩子,则根节点就是其父亲
    if (root->left == p || root->right == p) {
        return root;
    }

    // 在左子树中递归查找
    struct Node* leftResult = findFather(root->left, p);
    if (leftResult != NULL) {
        return leftResult;
    }

    // 在右子树中递归查找
    return findFather(root->right, p);
}

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);

    // 需要找到父亲的结点,比如 'e'
    // struct Node* targetNode = root->left->right;
    struct Node* targetNode = root;

    // 调用函数查找父亲节点
    struct Node* fatherNode = findFather(root, targetNode);

    // 输出结果
    if (fatherNode != NULL) {
        printf("The father of '%c' is '%c'\n", targetNode->data, fatherNode->data);
    } else {
        printf("'%c' is either the root or not found in the tree.\n", targetNode->data);
    }


    return 0;
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

C# Spire.Pdf将PDF文件转换为Word文件

一.开发框架&#xff1a; .NetCore6.0 工具&#xff1a;Visual Studio 2022 二.思路&#xff1a; 1.界面上传PDF文件&#xff0c;并保存 2.PDF文件转换为Word文件并保存 3.使用SHA256Hash判断文件是否已经转换过了&#xff0c;转换过了的话&#xff0c;就返回原先转换过的文…

数据——最为直接的答案

身处于这样一个数字化快速发展、竞争强烈的时代&#xff0c;不管是企业还是个人&#xff0c;大家都需要及时获取前沿动态信息&#xff0c;密切关注市场的变化。但是&#xff0c;在不计其数的企业中&#xff0c;到底行业top 是哪些企业引领潮流&#xff1f; 只有数据能告诉你最…

一款免费好用的制作电子杂志网站,发现新大陆~

你是不是也厌倦了传统纸质杂志的限制&#xff0c;想要尝试一种全新的阅读体验&#xff1f;那么&#xff0c;今天我要向你推荐的这款免费好用的制作电子杂志网站&#xff0c;绝对能让你眼前一亮&#xff01; 这款网站就是FLBOOK在线制作电子杂志平台&#xff0c;并且界面简洁、操…

设计模式之模版方法(TemplateMethod)

模版方法 钩子函数 回调函数 在父类里面有一个模版方法&#xff0c;在这个方法里面调用了op1&#xff0c;op2&#xff0c;op3… 在子类里面如果想要改变父类的op1和op2 只需要重写op1和op2&#xff0c;那么这个重写之后的方法&#xff0c;可以在父类里面直接调用的到 例子: J…

LabVIEW中NIPackageManager功能介绍

LabVIEW中PackageManager功能介绍 使用NIPackage Manager可安装、更新、修复和删除NI软件。 安装NI软件 使用PackageManager浏览和安装NI软件。 1. 在浏览产品选项卡上&#xff0c;单击产品类别以显示该类别中的可用产品。 2. 选择要安装的产品&#xff0c;然后单击…

20 个好用的一行 Java代码

今天分享给大家20个 令人惊叹的 Java一行代码&#xff0c;让你们的工作更轻松。一起来看看吧&#xff01; 1. 获取浏览器 Cookie 的值 使用document.cookie 来获取 Cookie 的值。 2. 将 RGB 转换为十六进制 3. 复制到剪贴板 使用 navigator.clipboard.writeText 轻松将任何文本…

Cesium 点线面实体

1.点 const point viewer.entities.add({ id: point, position: Cesium.Cartesian3.fromDegrees(113, 30), point: { pixelSize: 20, //像素 color: Cesium.Color.DEEPPINK, outlineColor: Cesium.Color.fromCssColorString(#fff), outlineWidth: 2, // 像素 }, }); 2.图标标注…

医院等级评审,离不开医院不良事件报告系统

医院不良事件报告系统全套源码 不良事件管理系统源码 不良事件上报系统对事件的报告、处置、跟踪、评价、分析、改进、学习等进行了综合管理&#xff0c;通过双向互评机制实现临床科室与职能部门之间的进一步互动&#xff0c;加强不良事件报告处置过程中的信息互通能力。 围绕…

Sonatype Nexus部署docker安装nexus3

Nexus是一个强大的Maven仓库管理器&#xff0c;它极大地简化了自己内部仓库的维护和外部仓库的访问。 1、查看可用的 Nexus3版本 可以通过 Sort by 查看其他版本的 nexus3&#xff0c;默认是最新版本 sonatype/nexus3:latest。 https://hub.docker.com/r/sonatype/nexus3/tags…

猫罐头如何选择?最受欢迎的5款猫罐头推荐!新手养猫速看!

对于一个刚入门的养猫新手来说&#xff0c;面对市面上琳琅满目的猫罐头选择确实让人头大。我们总想选到营养价值高的罐头&#xff0c;但又怕猫咪不喜欢吃&#xff0c;还担心选到不安全的产品。 作为家里有5只猫猫的铲屎官来说&#xff0c;养猫的这几年可以说是血泪史了&#x…

为什么你应该学习Go语言?

终于等到你&#xff01;Go语言——让你用写Python代码的开发效率编写C语言代码。 一、为什么互联网世界需要Go语言 世界上已经有太多太多的编程语言了&#xff0c;为什么又出来一个Go语言&#xff1f; 硬件限制&#xff1a;摩尔定律已然失效 摩尔定律&#xff1a;当价格不变…

LeetCode题94,44,145,二叉树的前中后序遍历,非递归

注意&#xff1a;解题都要用到栈 一、前序遍历 题目要求 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[…

LiveMedia视频监控汇聚管理平台功能中的CS客户端

平台具备独立的CS客户端可供客户使用&#xff0c;包含实时播放、监视组轮询、云镜控制、语音对讲、录像回放、报警查询、报警联动等。 实时视频 客户端支持单画面多画面显示&#xff0c;用户可选择任意一路或多路视频观看&#xff0c;视频窗口数量 1、3、6、8、9 直至 64 个可…

安装显卡驱动、安装cuda toolkit、安装cudnn

nvidia-smi查看&#xff0c;CUDA可以向下兼容&#xff0c;以我为例&#xff0c;可以安装12.0以下的版本&#xff1a; cuda toolkit https://developer.nvidia.com/cuda-toolkit-archive 如果 你前面没有安装vs&#xff0c;直接安装的这个&#xff0c;需要把CUDA里面的 Visua…

LLM大语言模型(典型ChatGPT)入门指南

文章目录 一、基础概念学习篇1.1 langchain视频学习笔记1.2 Finetune LLM视频学习笔记 二、实践篇2.1 预先下载模型&#xff1a;2.2 LangChain2.3 Colab demo2.3 text-generation-webui 三、国内项目实践langchain-chatchat 一、基础概念学习篇 1.1 langchain视频学习笔记 lan…

《005.SpringBoot之仓库管理系统》【有文档】

《005.SpringBoot之仓库管理系统》【有文档】 项目简介 [1]本系统涉及到的技术主要如下&#xff1a; 推荐环境配置&#xff1a;IDEA jdk1.8 Maven MySQL8.0 技术栈; 后台&#xff1a;SpringBootMybatisPlus; 前端&#xff1a;thymeleaf; [2]功能模块展示&#xff1a; 1.基础…

海康威视(iVMS)综合安防系统任意文件上传漏洞复现 [附POC]

文章目录 海康威视&#xff08;iVMS&#xff09;综合安防系统任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 海康威视&#xff08;iVMS&#xff09;综合安防系统任意文件上传漏洞复…

详解JDBC

JDBC简介 概念: jdbc就是使用java语言操作关系型数据库的一套API 全称 : (Java DataBase Connectivity) Java数据库连接 本质: 官方(sun公司)定义的一套操作所有关系型数据库的规则&#xff0c;即接口&#xff1b; 各个数据库厂商实现这套接口&#xff0c;提供数据库驱动j…

睿登RD6012P数控可调电源简单开箱评测

睿登RD6012P恒压恒流数控直流可调电源简单开箱评测&#xff0c;测试了一下 空载功耗和效率测试、恒流输出精度和电流回读精度测试、恒压输出精度和电压回读精度测试、输出纹波&#xff0c;还有简单分析了一下用到的芯片&#xff08;背面可看到的芯片&#xff0c;没有拆开看里面…

Java基础——方法参数值的传递机制

方法必须由其所在类或对象调用才有意义。 形参&#xff1a;方法声明时的参数。实参&#xff1a;方法调用时实际传给形参的参数值。 Java中方法的参数传递方式只有一种&#xff1a;值传递&#xff08;即将实际参数值得副本传入方法内&#xff09; 形参是基本数据类型&#xf…