【树】二叉树递归遍历和创建

news2024/11/26 3:34:18

二叉树的遍历

二叉树的遍历是将二叉树的每个结点访问且访问一次

遍历按根来说常用三种

设访问根结点记作V,遍历根的左子树记作L,遍历根的右子树记作R;

有:先序遍历VLR,中序遍历LVR,后序遍历LRV。

这个遍历是递归遍历的,例如中序遍历,先中序遍历左子树,访问根,最后中序遍历右子树。叶子结点也是一个二叉树,只不过它的左右子树为空,所以每一个结点都有且仅有一次输出。

先序遍历:A B C D E F G H

中序遍历:C B E D F A G H

后序遍历:C E F D B H G A

递归遍历

链式结构

先序

void PreOrder(BTNode* p)
{
    if (p != NULL)
    {
        printf("%c ", p->data);//根
        PreOrder(p->lchild);//左子树
        PreOrder(p->rchild);//右子树
    }
}

中序

void InOrder(BTNode* p)
{
    if (p != NULL)
    {
        InOrder(p->lchild);//先遍历左子树
        printf("%c ", p->data);//根
        InOrder(p->rchild);//右子树
    }
}

后序

void PastOrder(BTNode* p)
{
    if (p != NULL)
    {
        
        PastOrder(p->lchild);//左子树
        PastOrder(p->rchild);//右子树
        printf("%c ", p->data);//根
    }
}

顺序结构

中序

void InOrder_Ar(const int* nums, int i, int n)//i是根节点下标,n是规模
{
    if (i<n&&nums[i]!=-1)//不是空树
    {
        InOrder_Ar(nums, i* 2 + 1, n);//左子树
        printf("%d ", nums[i]);
        InOrder_Ar(nums, i * 2 + 2, n);//右子树
    }
    printf("%d ", nums[n]);
}

先序和后序将输出if里面的顺序改一下就好。

创建二叉树

使用数组创建二叉树

创建二叉树时需要直到其亲子联系,所以用先序遍历创建二叉树是最简便的

首先结点类型是一个结构体,包含左、右孩子的指针,和当前结点的值

typedef char ElemType;
typedef struct BTNode//BinaryTreeNode二叉树的结点类型
{
    BTNode* lchild;
    BTNode* rchild;
    ElemType data;//当前结点的数据
}BTNode,*BinaryTree;

然后,用字符串建立树,如果为空则输入#,不为空则申请空间,给结点赋值,并继续创建它的左、右子树。

这个传参时一定要用引用,不然左子树创建完接着不是创建当前结点的右子树,而是之前左子树的子树(重复使用前面的字符串了);使用引用后,用到的字符串不会重复

BTNode* CreatTreeStr(const char* &str)
{
    if (str == NULL || strlen(str) <= 0)return NULL;
    BTNode* s = NULL;
    if (*str != '#')
    {
        s = new(BTNode);
        if (s == NULL)exit(1);
        s->data = *str;//根
        s->lchild = CreatTreeStr(++str);//左
        s->rchild = CreatTreeStr(++str);//右
    }
    return s;
}

已知先序序列和中序序列,创建二叉树

先序遍历顺序找根,中序遍历分左右子树

初始时先序遍历第一个元素是根,给根赋值,然后在中序序列中找根的位置pos,分别创建左右子树;左子树范围为 从先序遍历的头的下一个元素往后数pos个;右子树的范围为剩下的;传参数时,先序序列和中序序列的范围都需要改变;

创建二叉树

BTNode* CreateBinaryTreePI(const char* pstr, const char* istr,int n)
{
    BTNode* s = NULL;
    if (n > 0)
    {
        s = new(BTNode);
        s->data = pstr[0];
        int pos = Find(istr, n, pstr[0]);
        if (pos == -1)exit(1);
        s->lchild = CreateBinaryTreePI(pstr+1, istr, pos);//先序遍历的下一个到其左子树结束一共pos个
        s->rchild = CreateBinaryTreePI(pstr+pos+1, istr+pos+1, n - pos-1);
    }
    return s;
}
BTNode* CreateBTPI(const char* pstr, const char* istr)
{
    int n = strlen(pstr);
    int m = strlen(istr);
    if (pstr == NULL || istr == NULL || n < 1 || m < 1 || n != m)return NULL;
    return CreateBinaryTreePI(pstr, istr, n);
}

找根的位置

int Find(const char* istr, int n, char ch)
{
    int pos = -1;
    for (int i = 0; i < n; i++)
    {
        if (istr[i] == ch)
        {
            pos = i;
            break;
        }
    }
    return pos;
}

主函数

已知先序序列和后序序列,创建二叉树

这跟上面的代码差不多,只是每次划分的范围需要注意。

后序序列的末尾是根,前半部分(0~pos)的pos个是左子树,后半部分(pos+1~n-1)的n-pos-1是右子树,因为末尾是根,所以需要-1;

中序序列用来找根的pos。

BTNode* CreateBinaryTreeIL(const char* istr, const char* lstr, int n)
{
    BTNode* s = NULL;
    if (n > 0)
    {
        s = new(BTNode);
        s->data = lstr[n-1];
        int pos = Find(istr, n, lstr[n-1]);
        if (pos == -1)exit(1);
        s->lchild = CreateBinaryTreeIL(istr, lstr, pos);
        s->rchild = CreateBinaryTreeIL(istr + pos + 1, lstr + pos, n - pos - 1);
    }
    return s;
}
BTNode* CreateBTIL(const char* istr, const char* lstr)
{
    int n = strlen(istr);
    int m = strlen(lstr);
    if (istr == NULL || lstr == NULL || n < 1 || m < 1 || n != m)return NULL;
    return CreateBinaryTreeIL(istr, lstr, n);
}

主函数

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

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

相关文章

设计模式 - 六大设计原则之ISP(接口隔离原则)

文章目录概述CaseBad ImplBetter Impl概述 接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09;,要求尽量将臃肿庞大的接口拆分成更小的和更具体的接口&#xff0c;让接口中只包含相关的方法。 接口隔离是为了高内聚、低耦合。 在实际的开发中&#x…

Altova MobileTogether 8.1

Altova MobileTogether 8.1 使用RecordsManager进行无代码开发的主要更新 可视化配置复杂条件的主要脚本扩展。 分层用户组。 客户端之间的UI兼容性模式 当开发人员希望应用程序在所有平台上看起来都一样&#xff0c;而不是使用每个平台的原生外观时&#xff0c;现在可以使用新…

蓝桥杯刷题016——最大子矩阵(尺取法+单调队列)

题目来源&#xff1a;最大子矩阵 - 蓝桥云课 (lanqiao.cn) 问题描述 小明有一个大小为 NM 的矩阵, 可以理解为一个 N 行 M 列的二维数组。 我们定义一个矩阵 m 的稳定度 f(m) 为f(m)max(m)−min(m), 其中 max(m) 表示矩阵 m 中的最大值, min(m) 表示矩阵 m 中的最小值。 现在小…

朴素贝叶斯分类

一、朴素贝叶斯法原理 1.基本原理 朴素贝叶斯法(Naive Bayes)是一种基础分类算法&#xff0c;它的核心是贝叶斯定理条件独立性假设。贝叶斯定理描述的是两个条件概率之间的关系&#xff0c;对两个事件A和B&#xff0c;由乘法法则易知(A∩B)P(A)P(B│A)P(B)P(A│B)(A∩B)P(A)P(…

离散数学与组合数学-06特殊的图

文章目录离散数学与组合数学-06特殊的图6.1 欧拉图6.1.1 哥尼斯堡七桥问题6.1.2 欧拉图的定义6.1.3 无向欧拉图的判定6.1.4 有向欧拉图的判定6.1.5 一笔画问题6.1.6 求回路6.2 哈密顿图6.2.1 周游世界问题6.2.2 哈密顿图的定义6.2.3 哈密顿图的必要条件6.2.4 哈密顿图的充分条件…

Hadoop基础之《(5)—MapReduce概述》

一、什么是MapReduce MapReduce将计算过程分为两个阶段&#xff1a;Map和Reduce。 1、Map阶段并行处理输入数据。 2、Reduce阶段对map结果进行汇总。 二、结构图 三、HDFS、Yarn、MapReduce三者之间的调用关系 HDFS三台服务器&#xff0c;第一台上有DataNode和NameNode。第二…

如何像程序员一样思考

如何像程序员一样思考 全世界越来越多的人发现了软件开发的乐趣和兴奋。一个你构建东西的职业&#xff0c;去打破它们&#xff0c;然后再把它们构建得更好。您可以经常设定自己的工作时间并与来自全球各地的客户一起工作的职业。一个可以自己当老板的职业&#xff1f;编程在 2…

android12.0(S) Launcher3 导入 AndroidStudio 调试编译

验证环境 aosp 12.0 源码&#xff0c;分支 android-12.0.0_r3 可以参考之前写的 android12.0(S) Pixel 3XL (QCOM 845) 编译刷机 AndroidStudio 版本 Android Studio Arctic Fox | 2020.3.1 Patch 4 gradle 版本 gradle-7.0.2-bin.zip gradle:7.0.4 二手 Pixel 3 XL一台可直…

[WUSTCTF2020]颜值成绩查询(布尔注入)

目录 信息收集 脚本 reference 信息收集 输入1出现固定的回显&#xff0c;输入2-4出现乱码 Hi admin, your score is: 100 输入其他特殊字符无回显&#xff0c;也无报错回显 采用布尔注入进行判断 布尔注入原理 代码存在SQL注入漏洞&#xff0c;然而页面即不会回显数据&am…

【C++算法图解专栏】一篇文章带你掌握尺取法(双指针)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为 0 基础刚入门数据结构与算法的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们一起交流~ &#x1f4da;专栏地址&#xff1a;https://blog.csdn.net/Newin…

java spring IOC xml方式工厂Bean操作

spring中有两种Bean 第一种 普通 Bean 就是我们在配置文件中 定义的类对象 创建bean 并定义相关的id和声明类对象 普通bean的特点在于 在配置文件中定义的类型 也就是返回类型 就比如 你定义的是一个 book类的类型 那你这个bean返回的 也比如是个book类型的对象 第二种 是在工…

模拟实现vector/迭代器失效问题

对于STL&#xff0c;我们不仅学会使用STL,还要了解其底层原理&#xff0c;这样一来&#xff0c;我们就能知道什么时候用string好&#xff0c;什么时候用vector&#xff0c;什么时候用list&#xff0c;哪种方法效率高等等。其次了解了STL的底层原理&#xff0c;也助于我们的C功力…

RTF、RIR、Steering Vector傻傻分不清

RTF&#xff1a; Relative transfer function&#xff0c;相对传递函数RIR: Room impulse response&#xff0c;空间冲击响应Steering vector: 导向矢量场景问题定义&#xff1a;空间中存在I个麦克风和J个声源&#xff0c;麦克风采集到的信号其中&#xff0c;麦克i的信号其中表…

一起自学SLAM算法:9.1 ORB-SLAM2算法

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 下面将从原理分析、源码解读和安装与运行这3个方面展开讲解ORB-SLAM2算法。 9.1.1 ORB-SLAM2原理分析 前面已经说过&#xff0c;ORB-SLAM2算法是特征点法的典型代表。因此在下面的分析中&#xff0c;首先介绍一…

被删库勒索了,怎么使用docker进行MySQL容器的管理?

大家觉得写还可以&#xff0c;可以点赞、收藏、关注一下吧&#xff01; 也可以到我的个人博客参观一下&#xff0c;估计近几年都会一直更新&#xff01;和我做个朋友吧&#xff01;https://motongxue.cn 起因&#xff1a;云服务器MySQL密码设置的太简单了&#xff0c;导致到被入…

路由策略实验

1.先配置IP和环回 [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 [R1-GigabitEthernet0/0/0]int g 0/0/1 [R1-GigabitEthernet0/0/1]ip add 22.1.1.1 24 [R1-GigabitEthernet0/0/1]q [R1]int l 0 [R1-LoopBack0]ip ad…

ETHDenver 2023 的 Cartesi BUIDLathon 项目创意

希望你在了解Cartesi之前&#xff0c;谨慎对待自己的行为。一旦你开始研究并搜寻可以使用Cartesi Rollups构建的项目或者应用&#xff0c;你就会陷入一个令人兴奋的螺旋洞穴中&#xff0c;你会上瘾。如果你想在2023年中建造一些很具有意义的事情&#xff0c;那你就来对地方了。…

Python01概述 基础语法 判断

Python概述 第二章-Python基础语法 01-字面量 02-注释 03-变量 04-数据类型 05-数据类型转换 06-标识符 07-运算符 08-字符串的三种定义方式 09-字符串的拼接 10-字符串格式化 11-字符串格式化的精度控制 12-字符串格式化的方式-快速写法 13-对表达式进行格式化 14-字符串格…

Java语法核心——面向对象编程

目录 面向过程思想概述 面向对象思想概述 面向对象思想特点及举例 类与对象的关系 类的定义 类与对象的案例(demo02) 对象内存存储机制 成员变量和局部变量的区别 private关键字 面向过程思想概述 我们回想一下&#xff0c;这几天我们完成一个需求的步骤&#xff1a;首…

echarts数据可视化项目搭建(一)

目录直角坐标系通用配置项tooltiptoolboxlegenddataZoom柱状图常见效果折线图常见效果散点图常见效果其他坐标系饼图基本实现常见效果地图地图基本展示不同城市颜色不同地图与散点图结合雷达图仪表盘本博客内容参考黑马课程&#xff0c;详细信息请参考以下网址 Bilibili官方黑…