二叉树的链式结构实现

二叉树的链式结构实现

    • 1. 链式存储
    • 2. 二叉树的遍历
      • 前序遍历
      • 中序遍历
      • 后序遍历
    • 3. 二叉树遍历的代码实现
      • 前序遍历
      • 中序遍历
      • 后序遍历
    • 4. 二叉树各种相关函数的实现
      • 二叉树节点个数
      • 二叉树叶子节点个数
      • 二叉树的高度
      • 二叉树第k层节点个数
      • 二叉树查找值为x的节点
    • 5. 代码验证

1. 链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。

typedef int BTDataType;
// 二叉链typedef struct BinaryTreeNode
{BTDataType data;// 当前节点值域struct BinaryTreeNode* left;// 指向当前节点左孩子struct BinaryTreeNode* right;// 指向当前节点右孩子
}BTNode;

2. 二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

前序遍历

前序遍历:访问根结点的操作发生在遍历其左右子树之前

根 - > 左子树 - > 右子树

前序遍历:
在这里插入图片描述

遍历顺序:1 -> 2 -> 3 -> NULL -> NULL -> NULL -> 4 -> 5 -> NULL - >NULL6 -> NULL - >NULL 。

中序遍历

中序遍历:访问根结点的操作发生在遍历其左右子树之中。

左子树 - > 根 - > 右子树

中序遍历:
在这里插入图片描述

遍历顺序:NULL -> 3 -> NULL -> 2 -> NULL -> 1 - > NULL - > 5 - > NULL -> 4 - > NULL -> 6 -> NULL

后序遍历

后序遍历:访问根结点的操作发生在遍历其左右子树之后。

左子树 - > 右子树 - > 根

后序遍历:
在这里插入图片描述

遍历顺序:NULL -> NULL -> 3 ->NULL -> 2 - > NULL -> NULL -> 5 - > NULL -> NULL -> 6 -> 4 -> 1。

3. 二叉树遍历的代码实现

首先,要实现二叉树的遍历,我们先手动创建一棵二叉树。

和链表类似,为了方便,我们定义一个申请节点的函数。

BTNode* BuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->left = NULL;newnode->right = NULL;return newnode;
}

创建如图所示的二叉树,只需要把左右指针连接好就可以了。

在这里插入图片描述

BTNode* CreatBinary()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}

前序遍历

#include <stdio.h>
#include <stdlib.h>// 二叉树前序遍历
void PrevOrder(BTNode*root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->data);PrevOrder(root->left);PrevOrder(root->right);
}int main()
{BTNode* boot = CreatBinary();PrevOrder(boot);return 0;
}

前序遍历递归图解:
在这里插入图片描述
在这里插入图片描述
运行结果如图:
在这里插入图片描述

中序遍历

// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}

运行结果如图:
在这里插入图片描述

后序遍历

// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}

运行结果如图:
在这里插入图片描述

4. 二叉树各种相关函数的实现

二叉树节点个数

方法一:

求二叉树的节点个数,我们可以遍历所有节点,如果该节点不是空就计数加一,最终就可以得到二叉树节点的个数,但是注意,尽量不要在递归函数内定义变量,因为函数在递归调用的时候,开辟的空间都是独立的,我们在函数内部定义的局部变量会重复定义,所以,我们最好定义一个全局变量,这样函数递归调用的时候使用的就是同一个变量。

int size = 0;int BTreeSize(BTNode* root)
{if (root == NULL){return size;}size++;BTreeSize(root->left);BTreeSize(root->right);
}

方法二:
求二叉树节点的个数,可以转换为:

  1. 如果节点为空,则没有节点返回0
  2. 如果节点不为空,节点的个数 = 左子树的个数 + 右子树的个数 + 自己(1)
int BTreeSize(BTNode* root)
{if (root == NULL){return 0;}return BTreeSize(root->left) + BTreeSize(root->right) + 1;
}

二叉树叶子节点个数

  1. 如果节点为,则叶子节点的个数为0,返回0
  2. 如果节点的左右指针都为空,则叶子节点的个数为1,返回1
  3. 如果不是叶子节点,也不是空节点,叶子节点的个数 = 左子树叶子节点的个数 + 右子树叶子节点的个数
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

二叉树的高度

  1. 如果节点为空,则高度为0,返回0
  2. 如果节点不为空,则树的高度 = 左右子树中的较大高度的子树 + 1
int BinaryTreeHeight(BTNode* root)
{if (root == NULL){return 0;}int left = BinaryTreeHeight(root->left);int right = BinaryTreeHeight(root->right);if (left > right){return left + 1;}else{return right + 1;}
}

二叉树第k层节点个数

  1. 如果节点为空,则返回0
  2. 如果节点不为空,k == 1,则第k层节点个数为1,返回1
  3. 如果节点不为空,二叉树第k层节点个数 = 左子树的的第k - 1层 + 右子树的的第k - 1层
    在这里插入图片描述
int BinaryTreeLevelKSize(BTNode* root, int k)
{assert(k > 0);if (root == NULL){return 0;}if (k == 1){return 1;}return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

二叉树查找值为x的节点

  1. 如果节点为空,则找不到返回NULL
  2. 如果节点不为空,先看根的值是否是x,如果不是,则查找左子树和右子树是否存在节点的值为x
  3. 如果左子树找到返回左子树找到的节点,如果右子树找到返回右子树找到的节点,如果左子树和右子树都找不到,则返回NULL
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* ret1 = BinaryTreeFind(root->left, x);if (ret1){return ret1;}BTNode* ret2 = BinaryTreeFind(root->right, x);if (ret2){return ret2;}return NULL;
}

5. 代码验证

验证树的节点如图:
在这里插入图片描述
验证代码如下:

int main()
{BTNode* root = CreatBinary();printf("BinaryTreeSize : %d\n", BinaryTreeSize(root));printf("BinaryTreeLeafSize : %d\n", BinaryTreeLeafSize(root));printf("BinaryTreeHeight : %d\n", BinaryTreeHeight(root));printf("BinaryTreeLevelKSize : %d\n", BinaryTreeLevelKSize(root,3));BTNode* ret = BinaryTreeFind(root, 3);if (ret == NULL){printf("找不到\n");}else{printf("找到了值为%d的节点\n", ret->data);}return 0;
}

运行结果如图:
在这里插入图片描述

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

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

相关文章

东莞IBM服务器维修之IBM x3630 M4阵列恢复

记录东莞某抖音电商公司送修一台IBM SYSTEM X3630 M4文档服务器RAID6故障导致数据丢失的恢复案例 时间&#xff1a;2024年02月20日&#xff0c; 服务器品牌&#xff1a;IBM System x3630 M4&#xff0c;阵列卡用的是DELL PERC H730P 服务器用途和用户位置&#xff1a;某抖音电…

Fastapi进阶用法,路径参数,路由分发,查询参数等详解

文章目录 1、路径操作1.路径操作装饰器1.tags 标签2.summary 接口描述的总结信息3.describe: 接口信息的详细描述4.response_description&#xff1a;响应描述5.deprecated&#xff1a;接口是否废弃&#xff0c;默认是False 2.fastapi路由分发include_router 2、请求与响应2.1、…

【java-集合框架】ArrayList类

&#x1f4e2;java基础语法&#xff0c;集合框架是什么&#xff1f;顺序表的底层模拟实现都是看本篇前的基础必会内容&#xff0c;本篇不再赘述&#xff0c;详情见评论区文章。 &#x1f4e2;编程环境&#xff1a;idea 【java-集合框架】ArrayList类 1. 先回忆一下java代码中常…

泽攸科技JS系列高精度台阶仪在半导体领域的应用

泽攸科技JS系列高精度台阶仪是一款先进的自主研发的国产台阶仪&#xff0c;采用了先进的扫描探针技术。通过扫描探针在样品表面上进行微观测量&#xff0c;台阶仪能够准确获取表面形貌信息。其工作原理基于探针与样品表面的相互作用力&#xff0c;通过测量探针的微小位移&#…

JVM相关面试题

【面试题一】谈谈JVM内存模型 JVM内存区域的划分&#xff0c;之所以划分是为了JVM更好的进行内存管理。就好比一间卧室&#xff0c;这块放床&#xff0c;这块放个电脑桌&#xff0c;每块地方各自有各自的功能&#xff0c;床用来睡觉&#xff0c;电脑桌用来办公打游戏。而JVM划…

C++——基础语法(3):内联函数、auto关键字、基于范围的for循环、空指针nullptr

6. 内联函数 在函数前加入inline修饰即可将函数变为内联函数。所谓内联函数&#xff0c;就是在编译时C编译器会将函数体在调用内联函数的地方展开&#xff0c;从而省去了调用函数的栈帧开销&#xff0c;提高程序运行效率。 inline int Add(int a, int b) {return a b; } int …

SpringBoot源码解读与原理分析(三十三)SpringBoot整合JDBC(二)声明式事务的生效原理和控制流程

文章目录 前言10.3 声明式事务的生效原理10.3.1 TransactionAutoConfiguration10.3.2 TransactionManagementConfigurationSelector10.3.3 AutoProxyRegistrar10.3.4 InfrastructureAdvisorAutoProxyCreator10.3.5 ProxyTransactionManagementConfiguration10.3.5.1 Transactio…

Datawhale-Sora技术原理分享

目录 Sora能力边界探索 Sora模型训练流程 Sora关键技术拆解 物理引擎的数据进行训练 个人思考与总结 参考 https://datawhaler.feishu.cn/file/KntHbV3QGoEPruxEql2c9lrsnOb

袁庭新ES系列12节 | Elasticsearch高级查询操作

前言 上篇文章讲了关于Elasticsearch的基本查询操作。接下来袁老师为大家带来Elasticsearch高级查询部分相关的内容。Elasticsearch是基于JSON提供完整的查询DSL&#xff08;Domain Specific Language&#xff1a;领域特定语言&#xff09;来定义查询。因此&#xff0c;我们有…

消息中间件篇之Kafka-消息不丢失

一、 正常工作流程 生产者发送消息到kafka集群&#xff0c;然后由集群发送到消费者。 但是可能中途会出现消息的丢失。下面是解决方案。 二、 生产者发送消息到Brocker丢失 1. 设置异步发送 //同步发送RecordMetadata recordMetadata kafkaProducer.send(record).get();//异…

【Java程序设计】【C00296】基于Springboot的4S车辆管理系统(有论文)

基于Springboot的4S车辆管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的4S店车辆管理系统 本系统分为销售员功能模块、管理员功能模块以及维修员功能模块。 管理员功能模块&#xff1a;管理员登录进入4S…

少儿编程热潮背后的冷思考、是不是“智商税”?

在科技飞速发展的今天&#xff0c;编程已成为一项基础技能&#xff0c;如同数学和语言一样&#xff0c;被认为是未来社会的重要通行证。随之而来的是少儿编程教育的火爆&#xff0c;各种编程班、在线课程如雨后春笋般涌现&#xff0c;吸引了无数家长的目光。然而&#xff0c;这…

测试环境搭建整套大数据系统(七:集群搭建kafka(2.13)+flink(1.14)+dinky+hudi)

一&#xff1a;搭建kafka。 1. 三台机器执行以下命令。 cd /opt wget wget https://dlcdn.apache.org/kafka/3.6.1/kafka_2.13-3.6.1.tgz tar zxvf kafka_2.13-3.6.1.tgz cd kafka_2.13-3.6.1/config vim server.properties修改以下俩内容 1.三台机器分别给予各自的broker_id…

MapGIS农业信息化解决方案(2)

农业资源采集与调查 农业各项生产活动与农业资源息息相关,对农业资源进行调查,摸清农业家底, 为构筑农业“一张图”核心数据库奠定数据基础。MapGIS 农业资源采集与调查系统集成遥感、手持终端等调查技术,为农业资源采集提供实用、简捷的采集调查和信息录入工具,实现农田…

PCB设计十大黄金准则

PCB设计十大黄金准则 控制走线长度控制走线长度&#xff0c;顾名思义&#xff0c;即短线规则&#xff0c;在进行PCB设计时应该控制布线长度尽量短&#xff0c;以免因走线过长引入不必要的干扰&#xff0c;特别是一些重要信号线&#xff0c;如时钟信号走线&#xff0c;务必将其…

linux查看socket信息

netstat netstat 是一个用于显示网络相关信息的命令行工具。它可以显示当前系统的网络连接状态、路由表、接口统计信息等。 下面是一些常见的 netstat 命令选项和用法&#xff1a; 显示所有活动的网络连接&#xff1a; netstat -a 显示所有正在监听的端口&#xff1a; ne…

深度学习 精选笔记(4)线性神经网络-交叉熵回归与Softmax 回归

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增)&#xff0c;以达到集多方教程的精华于一文的目的。 ③非常推荐上面&#xff08;学习参考&#x…

现代化数据架构升级:毫末智行自动驾驶如何应对年增20PB的数据规模挑战?

毫末智行是一家致力于自动驾驶的人工智能技术公司&#xff0c;其前身是长城汽车智能驾驶前瞻分部&#xff0c;以零事故、零拥堵、自由出行和高效物流为目标&#xff0c;助力合作伙伴重塑和全面升级整个社会的出行及物流方式。 在自动驾驶领域中&#xff0c;是什么原因让毫末智行…

【设计模式】5种创建型模式详解

创建型模式提供创建对象的机制,能够提升已有代码的灵活性和复用性。 常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。不常用的有:原型模式。一、单例模式 1.1 单例模式介绍 1 ) 定义 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模…

Jupyterlab 和 JupyternoteBook 修改默认路径

Jupyterlab 和 JupyternoteBook 修改默认路径 在使用 JupyterLab 或 Jupyter Notebook 进行数据分析、机器学习项目时&#xff0c;经常会遇到需要修改默认工作目录的需求。默认情况下&#xff0c;JupyterLab 和 Jupyter Notebook 会在启动时打开你的用户目录&#xff08;例如&…