909-2015-T3

文章目录

  • 1.原题
  • 2.算法思想
    • 2.1.求树的高度
    • 2.2.求路径
  • 3.关键代码
  • 4.完整代码
  • 5.输出结果

1.原题

试编写算法,求给定二叉树上从根节点到叶子节点的一条路径长度等于树的深度减一的路径(即列出从根节点到该叶子节点的节点序列),若这样的路径存在多条,则输出路径终点在“最左”的一条。

2.算法思想

计算出树的高度,然后再进行类前序遍历,输出路径为最深的、最靠左的一条。分为两部分。1.求树的高度;2.求路径

2.1.求树的高度

这个算法在14年某个题已经涉及到了。通过遍历的方式得出每一个结点的左子树高度和右子树高度,而该结点的高度就是左子树高度和右子树高度较大的那一个+1

2.2.求路径

由于是求最靠左的一条、最深的一条路径,那么用类先序遍历的方式进行探索最有优势。根据先序遍历的特点,我们第一次找到的路径即为最左边的。同时引入了一个变量isFound,这样在找到一条路径之后可以更快跳过后续的递归嵌套。

3.关键代码

/**
 * @struct treeNode
 * @brief 二叉树节点的结构体
 */
struct treeNode {
    int data; /**< 节点存储的数据 */
    struct treeNode *lchild; /**< 左子节点指针 */
    struct treeNode *rchild; /**< 右子节点指针 */
};

/**
 * @brief 计算二叉树的高度。
 *
 * 通过递归地计算左右子树的高度,返回树的高度。
 *
 * @param root 二叉树根节点指针。
 * @return 返回二叉树的高度。
 */
int treeHeight(struct treeNode *root) {
    if (root == NULL) {
        return 0; // 如果根节点为空,返回0表示树的高度为0
    } else {
        int leftHeight = treeHeight(root->lchild); // 递归计算左子树的高度
        int rightHeight = treeHeight(root->rchild); // 递归计算右子树的高度

        // 返回左右子树中较大的高度加上当前节点的高度(加1)
        return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
    }
}

/**
 * @brief 在二叉树中查找具有特定深度的路径
 *
 * 通过递归遍历二叉树,查找根到叶子节点的路径,其深度等于指定高度,并打印该路径。
 *
 * @param root 二叉树根节点指针。
 * @param isFound 指向一个布尔值的指针,用于判断是否已找到特定深度的路径。
 * @param height 期望的路径深度。
 * @param depth 当前递归深度。
 * @param path 用于存储路径节点值的数组。
 */
void findPath(struct treeNode *root, bool *isFound, int height, int depth, int path[]) {
    if (root == NULL || (*isFound) == true) {
        return; // 如果根节点为空或已找到路径,则直接返回
    }

    path[depth] = root->data; // 将当前节点值存入路径数组中

    if (depth == height - 1) {
        (*isFound) = true; // 标记已找到路径
        for (int i = 0; i < height; i++) {
            printf("%d ", path[i]); // 打印路径节点值
        }
        printf("\n");
        return;
    } else {
        depth += 1; // 增加深度
        findPath(root->lchild, isFound, height, depth, path); // 递归遍历左子树
        findPath(root->rchild, isFound, height, depth, path); // 递归遍历右子树
    }
}

/**
 * @brief 寻找二叉树中指定深度的路径
 *
 * 通过计算二叉树的高度,创建对应高度的数组,并在树中查找深度为高度减一的路径。
 * 找到后打印该路径上的节点值。
 *
 * @param root 二叉树根节点指针。
 */
void findSpecialPath(struct treeNode *root) {
    int height = treeHeight(root); // 计算二叉树的高度
    int path[height]; // 创建与高度相同大小的数组,用于存储路径节点值
    bool isFound = false; // 指示是否找到特定深度的路径

    findPath(root, &isFound, height, 0, path); // 查找特定深度的路径
}

4.完整代码

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

/**
 * @struct treeNode
 * @brief 二叉树节点的结构体
 */
struct treeNode {
    int data; /**< 节点存储的数据 */
    struct treeNode *lchild; /**< 左子节点指针 */
    struct treeNode *rchild; /**< 右子节点指针 */
};

/**
 * @brief 计算二叉树的高度。
 *
 * 通过递归地计算左右子树的高度,返回树的高度。
 *
 * @param root 二叉树根节点指针。
 * @return 返回二叉树的高度。
 */
int treeHeight(struct treeNode *root) {
    if (root == NULL) {
        return 0; // 如果根节点为空,返回0表示树的高度为0
    } else {
        int leftHeight = treeHeight(root->lchild); // 递归计算左子树的高度
        int rightHeight = treeHeight(root->rchild); // 递归计算右子树的高度

        // 返回左右子树中较大的高度加上当前节点的高度(加1)
        return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
    }
}

/**
 * @brief 在二叉树中查找具有特定深度的路径
 *
 * 通过递归遍历二叉树,查找根到叶子节点的路径,其深度等于指定高度,并打印该路径。
 *
 * @param root 二叉树根节点指针。
 * @param isFound 指向一个布尔值的指针,用于判断是否已找到特定深度的路径。
 * @param height 期望的路径深度。
 * @param depth 当前递归深度。
 * @param path 用于存储路径节点值的数组。
 */
void findPath(struct treeNode *root, bool *isFound, int height, int depth, int path[]) {
    if (root == NULL || (*isFound) == true) {
        return; // 如果根节点为空或已找到路径,则直接返回
    }

    path[depth] = root->data; // 将当前节点值存入路径数组中

    if (depth == height - 1) {
        (*isFound) = true; // 标记已找到路径
        for (int i = 0; i < height; i++) {
            printf("%d ", path[i]); // 打印路径节点值
        }
        printf("\n");
        return;
    } else {
        depth += 1; // 增加深度
        findPath(root->lchild, isFound, height, depth, path); // 递归遍历左子树
        findPath(root->rchild, isFound, height, depth, path); // 递归遍历右子树
    }
}

/**
 * @brief 寻找二叉树中指定深度的路径
 *
 * 通过计算二叉树的高度,创建对应高度的数组,并在树中查找深度为高度减一的路径。
 * 找到后打印该路径上的节点值。
 *
 * @param root 二叉树根节点指针。
 */
void findSpecialPath(struct treeNode *root) {
    int height = treeHeight(root); // 计算二叉树的高度
    int path[height]; // 创建与高度相同大小的数组,用于存储路径节点值
    bool isFound = false; // 指示是否找到特定深度的路径

    findPath(root, &isFound, height, 0, path); // 查找特定深度的路径
}

/**
 * @brief 创建新的二叉树节点。
 *
 * @param data 新节点存储的数据。
 * @return 指向新节点的指针。
 */
struct treeNode *createNode(int data) {
    struct treeNode *newNode = (struct treeNode *) malloc(sizeof(struct treeNode));
    newNode->data = data;
    newNode->lchild = NULL;
    newNode->rchild = NULL;
    return newNode;
}

/**
 * @brief 以括号表示法打印二叉树。
 *
 * @param root 二叉树根节点指针。
 */
void printBinaryTree(struct treeNode *root) {
    if (root == NULL) {
        return;
    }
    printf("(%d", root->data);
    if (root->lchild != NULL || root->rchild != NULL) {
        printf(" ");
        if (root->lchild == NULL) {
            printf("( )");
        } else {
            printBinaryTree(root->lchild);
        }
        printf(" ");
        if (root->rchild == NULL) {
            printf("( )");
        } else {
            printBinaryTree(root->rchild);
        }
    }
    printf(")");
}

/**
 * @brief 以树的结构方式打印二叉树。
 *
 * @param root 二叉树根节点指针。
 * @param space 节点之间的间距。
 */
void printTreeStructure(struct treeNode *root, int space) {
    if (root == NULL) {
        return;
    }

    int count = 5; // 调整节点之间的间距

    printTreeStructure(root->rchild, space + count);

    for (int i = 0; i < space; i++) {
        printf(" ");
    }
    printf("%d\n", root->data);

    printTreeStructure(root->lchild, space + count);
}


int main() {
    struct treeNode *root = createNode(10);  // 根节点为10
    root->lchild = createNode(5);
    root->rchild = createNode(15);
    root->lchild->lchild = createNode(3);
    root->rchild->lchild = createNode(12);
    root->rchild->rchild = createNode(18);
    root->rchild->lchild->rchild = createNode(13);
    root->rchild->rchild->rchild = createNode(9);


    // 以括号表示法打印二叉树
    printf("Binary Tree Structure (Parenthesis Representation):\n");
    printBinaryTree(root);

    // 以树的结构方式打印二叉树
    printf("\nBinary Tree Structure:\n");
    printTreeStructure(root, 0);

    int height = treeHeight(root);
    printf("Height of the tree: %d\n", height);

    // 寻找特定路径并打印
    printf("Special Path with length equal to tree depth - 1: \n");
    findSpecialPath(root);

    return 0;
}

5.输出结果

在这里插入图片描述

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

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

相关文章

解决 VSCode 配置远程连接,过程试图写入的管道不存在

解决 VSCode 配置远程连接&#xff0c;过程试图写入的管道不存在

【数据结构】链表中二级指针的应用

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 (注:为方便演示本篇使用的x86系统,因此指针的大小为4个字节) 目录 &#x1f4cc;形参的改变不影响实参! 1.调用函数更改整型时传值调用与传址调用的区别 &#x1f38f;传值…

掌握Katalon Studio 导入 swagger 接口文档,接口测试效率提升100%

katalon studio大家都已经不陌生了&#xff0c;是一款现在非常主流的自动化测试工具&#xff0c;包括了web、api、APP&#xff0c;甚至PC应用程序都可以使用它来完成自动化测试。 swagger是一款RESTFUL接口的文档在线自动生成软件&#xff0c;swagger是一个规范和完整的框架&a…

【数据库】数据库中的检查点Checkpoint,数据落盘的重要时刻

检查点(checkpoint) ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定…

PostMan接口测试教程

1、下载和安装 Postman: 前往 Postman 官网 &#xff08;https://www.postman.com&#xff09;&#xff0c;下载适用于你的操作系统的 Postman 客户端。 执行下载后的安装程序&#xff0c;并按照安装向导的指引完成安装过程。 2、创建一个新的集合&#xff1a; 打开 Postma…

LangChain库简介

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

那仰望的人

心底的孤独和叹息

PC访问华为昇腾开发板的摸索过程

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 最近要折腾华为昇腾开发板&#xff08;官方名称叫&#xff1a;Atlas 200I DK&#xff09;。先是按照官方教程折腾&#xff1a;Atlas200DK环境部署。我发现…

数组扩展方法(一)

Array.prototype.forEach MDN解释forEach()方法是对数组的每个元素执行一个给定的函数&#xff0c;换句话来说就是在调用forEach()方法的时候&#xff0c;需要传入一个回调函数callback&#xff0c;循环每个数组内部元素时都会执行一次传入的回调函数callback forEach()方法的…

Python通过selenium调用IE11浏览器报错解决方法

前提 正常安装Python 工具&#xff0c;selenium 包可以正常导入。IE浏览器驱动 IEDriverServer.exe 已经正确放置到已经添加path目录的文件下。 报错现象&#xff1a; 解决方法 打开浏览器进入 internet 选项 切换到安全页签 &#xff0c;去除“应用保护模式” 再次调用验证…

苍穹外卖项目笔记(4)——菜品管理

菜品管理 主要功能模块&#xff1a;新建菜品、修改菜品、启用禁用菜品、菜品的分页查询、删除菜品 代码&#xff1a;GitHub - Echo0701/take-out 1 公共字段自动填充 公共字段指的是业务表中有一些相同的字段&#xff0c;比如创建人、创建时间、修改人、修改时间等&#xff…

QT搭建的Ros/librviz的GUI软件

1.前言 开发初期学习了下面博主的文章&#xff0c;也报了他在古月局的课&#xff0c;相当于感谢吧。 ROS Qt5 librviz人机交互界面开发一&#xff08;配置QT环境&#xff09;-CSDN博客​​​​​​​r 软件前期也是参考他的开源项目 GitHub - chengyangkj/Ros_Qt5_Gui_App …

如何实现数据通过表格批量导入数据库

文章目录 1. 准备工作2. 创建数据库表3. 编写导入脚本4. 优化和拓展4.1 批量插入的优势4.2 错误处理4.3 数据验证4.4 数据转换 5. 总结 &#x1f389;如何实现数据通过表格批量导入数据库 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&…

常见的8个JMeter压测问题

为什么在JMeter中执行压力测试时&#xff0c;出现连接异常或连接重置错误&#xff1f; 答案&#xff1a;连接异常或连接重置错误通常是由于服务器在处理请求时出现问题引起的。这可能是由于服务器过载、网络故障或配置错误等原因导致的。 解决方法&#xff1a; 确定服务器的…

OSG文字-osgText3D(5)

osgText3D 三维立体文字比二维平面文字显示效果更好&#xff0c;相对二维平面文字&#xff0c;它有非常好的立体显示效果。 在实际虚拟现实项目中&#xff0c;过多使用三维立体文字会降低染效率&#xff0c;加重渲染负担&#xff0c;相对平面二维文字&#xff0c;它占用的内存是…

Linux C IO复用

IO复用 概述IO模型阻塞式IO非阻塞式IOIO复用select、poll、epoll异同 信号驱动式IO异步IO select函数select示例代码 poll函数poll示例代码 epoll函数创建  epoll_create注册、修改、删除  epoll_ctl轮询 I/O 事件的发生  epoll_waitepoll示例代码 基于TCP和epoll在线多人…

APP自动化之Poco框架

今天给大家介绍一款自动化测试框架Poco&#xff0c;其脚本写法非常简洁、高效&#xff0c;其元素定位器效率更快&#xff0c;其本质基于python的第三方库&#xff0c;调试起来也会非常方便&#xff0c;能够很好的提升自动化测试效率&#xff0c;节省时间。 (一&#xff09;背景…

DDD神药:去哪儿结合DDD,实现架构大调优

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#x…

浅谈低压绝缘监测及定位系统在海上石油平台的研究与应用

安科瑞 华楠 摘要&#xff1a;海上石油平台低压系统与陆地电力系统有很大区别&#xff0c;其属于中性点绝缘系统&#xff0c;在出现单相接地故障时&#xff0c;系统允许带故障正常运行2 h&#xff0c;保证海上重要电气设备不会立即关停。现以渤海某海上平台为例&#xff0c;其…

Leetcode—13.罗马数字转整数【简单】

2023每日刷题&#xff08;三十七&#xff09; Leetcode—13.罗马数字转整数 算法思想 当前位置的元素比下个位置的元素小&#xff0c;就减去当前值&#xff0c;否则加上当前值 实现代码 int getValue(char c) {switch(c) {case I:return 1;case V:return 5;case X:return 1…