数据结构初阶 —— 二叉树链式结构

news2025/1/10 3:16:40

目录

 一,二叉树链式结构

二,二叉树的遍历(四种)

前序遍历

中序遍历

后序遍历

层序遍历

三,二叉树接口

四,试题


 一,二叉树链式结构

  • 普通二叉树的增删查改,意义不大;
  • 普通二叉树+搜索树规则,增删查改才有价值;
//二叉树链式结构
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;

//创建节点
BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("BuyNode");
		exit(-1);
	}
	node->_data = x;
	node->_left = node->_right = NULL;
	return node;
}

//自定义二叉树
BTNode* CreatBinaryTree()
{
	BTNode* nodeA = BuyNode('A');
	BTNode* nodeB = BuyNode('B');
	BTNode* nodeC = BuyNode('C');
	BTNode* nodeD = BuyNode('D');
	BTNode* nodeE = BuyNode('E');
	BTNode* nodeF = BuyNode('F');
	nodeA->_left = nodeB;
	nodeA->_right = nodeC;
	nodeB->_left = nodeD;
	nodeC->_left = nodeE;
	nodeC->_right = nodeF;
	return nodeA;
}

二,二叉树的遍历(四种)

  • 前序遍历,根 \rightarrow 左子树 \rightarrow 右子树;
  • 中序遍历,左子树 \rightarrow 根 \rightarrow 右子树;
  • 后序遍历,左子树 \rightarrow 右子树 \rightarrow 根;
  • 层序遍历,一层一层遍历;

注:深度优先遍历(前序、中序、后序),广度优先遍历(层序);

前序遍历

//前序遍历
void PreOrder(BTNode* root)
{
	if (root == NULL)
		return;
	printf("%c ", root->_data);
	PreOrder(root->_left);
	PreOrder(root->_right);
}

中序遍历

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
		return;
	InOrder(root->_left);
	printf("%c ", root->_data);
	InOrder(root->_right);
}

后序遍历

//后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
		return;
	PostOrder(root->_left);
	PostOrder(root->_right);
	printf("%c ", root->_data);
}

层序遍历

//层序遍历-利用队列
//一个节点出列,入列其子节点
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
    QDataType data;
    struct QueueNode* next;
}QueueNode;
typedef struct Queue
{
    QueueNode* phead;
    QueueNode* ptail;   
}

void LevelOrder(BTNode* root)
{
    Queue q;
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        printf("%c ", front->val);
        if(front->left)
            QueuePush(&q, front->left);
        if(front->right)
            QueuePush(&q, front->right);
    }
    printf("\n");
    QueueDestroy(&q);
}

三,二叉树接口

//求二叉树节点个数-递归
//方法一,全局变量或static
int size = 0; 
void BinaryTreeSize(BTNode* root)
{
	if (root)
		size++;
	else
		return;
	BinaryTreeSize(root->_left);
	BinaryTreeSize(root->_right);
}

//方法二,局部变量-传址
void BinaryTreeSize(BTNode* root, int* psize)
{
	if (root)
		(*psize)++;
	else
		return;
	BinaryTreeSize(root->_left, psize);
	BinaryTreeSize(root->_right, psize);
}

//方法三,返回值
int BinaryTreeSize(BTNode* root)
{
	if (root)
		return 1 + BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right);
	else
		return 0;
}
//求二叉树叶子节点个数
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);
}
//求二叉树第k层节点个数
//当前树第K层节点个数 = 其左子树的第K-1层节点个数 + 其右子树的第K-1层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
//求二叉树深度
//当前树深度 = max(左子树深度, 右子树深度) + 1;
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
		return 0;
	int leftDepth = BinaryTreeDepth(root->_left);
	int rightDepth = BinaryTreeDepth(root->_right);
	return leftDepth > rightDepth ? (1 + leftDepth) : (1 + rightDepth);
}
//二叉树查找值为x的节点
//先当前节点查找,没有,在去左子树查找,没有,在取右子树查找
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->_data == x)
		return root;

	BTNode* retLeft = BinaryTreeFind(root->_left, x);
	if (retLeft)
		return retLeft;

	BTNode* retRight = BinaryTreeFind(root->_right, x);
	if (retRight)
		return retRight;

	return NULL;
}
//二叉树的销毁
void BinaryTreeDestory(BTNode* root)
{
    if(root==NULL)
        return;
    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    free(root);
}
//判断二叉树是否是完全二叉树
//利用层序,空也入列,完全二叉树非空是连续的
bool BinaryTreeComplete(BTNode* root)
{
    Queue q;
    QueueInit(&q);
    if(root)
        QueuePush(&q, root);
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        if(front == NULL)
            break;
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
    }
    while(!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);
        if(front)
        {
            QueueDestroy(&q);
            return false; 
        }
    }
    QueueDestroy(&q);
    return true;
}

四,试题

  • 二叉树的前序遍历(设置子程序);
  • 二叉树的中序变量(设置子程序);
  • 二叉树的后序遍历(设置子程序);
  • 单值二叉树;
  • 两颗树是否相等(时间复杂度O(N)、空间复杂度即高度O(N));
  • 另一颗树的子树;
  • 对称二叉树;
  • 根据指定前序遍历的字符串,重构此二叉树;

注:完全二叉树O(log(N));

(前序/后序:可得到根,中序:可得到左右树的区间)

  • 前序+中序,可重建树;
  • 后序+中序,可重建树;
  • 前序+后序,不可重建树;

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

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

相关文章

JavaScript基础扫盲

博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE初阶 本篇文章为大家带来JavaScript的学习,一图胜千言~~~ 目录 文章目录 1.1 JavaScript (简称 JS) 1.2 JavaScript发展历史 1.3 JavaScript运行过程 二、JavaScript的基础语法 2.1 …

Linux内核源码分析-进程调度(五)-组调度

出现的背景 总结来说是希望不同分组的任务在高负载下能分配可控比例的CPU资源。为什么会有这个需求呢,假设多用户计算机系统每个用户的所有任务划分到一个分组中,A用户90个任务,而B用户只有10个任务(这100个任务假设都是优先级一…

物联网手势控制小车所遇问题与解决方案

LCD1602无法显示问题 问题描述:按照开源社区教程完成LCD1602驱动显示程序的编写,成功点亮屏幕,开启背光,但无法观察到显示数据。 分析过程与解决方案: 1.是否IIC地址不对 使用以下代码扫描IIC总线上的设备&#xf…

Go学习圣经:队列削峰+批量写入 超高并发原理和实操

说在前面: 本文是《Go学习圣经》 的第二部分。 第一部分请参见:Go学习圣经:0基础精通GO开发与高并发架构(1) 现在拿到offer超级难,甚至连面试电话,一个都搞不到。 尼恩的技术社群中&#xf…

K近邻算法实现红酒数据集分类

目录 1. 作者介绍2. K近邻算法介绍2.1 K基本原理2.2 算法优缺点 3. KNN红酒数据集分类实验3.1 获取红酒数据集3.2 KNN算法3.3 完整代码 4. 问题分析参考链接(可供参考的链接和引用文献) 1. 作者介绍 路治东,男,西安工程大学电子信…

面试问题汇总

最近面试了几家公司,对问到的问题汇总一下。 Unity 是左手坐标系还是右手坐标系? 这个题靠记忆答的答错了,是左手坐标系。 大拇指指的方向是X轴,食指指的方向是Y轴方向,中指指的方向Z轴方向。 场景中游戏物体Activity为false,G…

C语言字符串函数和内存函数的介绍与模拟实现

0.前言 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 1.字符串函数介绍与模拟实现 C语言本身就带有一些库函数,所…

研发工程师玩转Kubernetes——CPU配额

在一个Pod中,可以有多个容器,比如一个主要业务容器和若干辅助业务容器。如果辅助业务容器内程序有问题,导致占用了大量的CPU资源,进而影响了主要业务容器的执行效率,那就需要进行干涉了。本节我们将使用“资源配额”来…

Edgedetect

边缘检测,检测上升沿 对于 8 位矢量中的每个位,检测输入信号何时从一个时钟周期中的 0 变为下一个时钟周期的 1(类似于正边沿检测)。输出位应在发生 0 到 1 转换后设置周期。 以下是一些示例。为清楚起见,in[1] 和 pe…

Jenkins+GitLab+Docker搭建前端自动化构建镜像容器部署(无本地证书,映射版本)

前言 🚀 需提前安装环境及知识点: 1、Docker搭建及基础操作 2、DockerFile文件描述 3、Jenkins搭建及基础点 🚀 目的: 将我们的前端项目打包成一个镜像容器并自动发布部署,可供随时pull访问 一、手动部署镜像及容器 1…

【Linux】线程分离 | 线程库 | C++调用线程 | 线程局部存储

文章目录 1. 线程分离1. 为什么要线程分离?2. 具体使用3. 为什么有时候分离在调用join 会正常运行? 2. 如何理解线程库?如何理解 先描述 在组织? 3. C中使用多线程4. 线程局部存储局部变量全局变量 1. 线程分离 1. 为什么要线程分…

服务器虚拟化部署

服务器虚拟化部署 1、背景2、目的3、环境4、部署4.1、部署VMware ESXi4.1.1、准备工作4.1.2、部署ESXi4.1.3、配置ESXi4.1.4 、部署虚拟机 1、背景 项目上利旧9台服务器,项目需要使用15台服务器,外购已经没有项目硬件采购预算,只能从目前的…

自定义HikariCP连接池

文章目录 一、简介1、概述2、地址 二、配置参数1、Hikari原生参数2、Springboot中参数 三、springboot中使用四、自定义数据源1、各模块2、完整代码3、多数据源 五、多数据源dynamic中使用1、简介2、引入依赖3、参数配置 六、XMind整理 一、简介 1、概述 官方解释&#xff1a…

zabbix 自动发现与自动注册、部署 zabbix 代理服务器及部署 Zabbix 高可用集群

目录 一、zabbix 自动发现二、zabbix 自动注册(对于 agent2 是主动模式)三、部署 zabbix 代理服务器四、部署 Zabbix 高可用集群五、Zabbix 监控 Windows 系统六、Zabbix 监控 java 应用七、Zabbix 监控 SNMP 一、zabbix 自动发现 zabbix 自动发现&…

Nautilus Chain开启全球行,普及Layer3概念加速其采用

在去年,在 2022 年,Vitalik 进一步提出了 Layer3 的概念与早期形态,期盼弥补目前链体系存在的不足,并为 Layer3 提出了三大目标,即Layer2 用于扩展,Layer3 用于定制功能,如隐私;Laye…

【C++】哈希表特性总结及unordered_map和unordered_set的模拟实现

✍作者:阿润菜菜 📖专栏:C 文章目录 前言一、哈希表的特性 - 哈希函数和哈希冲突1 哈希函数2. 哈希冲突 二、闭散列的实现 -- 开放地址法1. 定义数据结构2.insert()3.Find()4. Erase()5.仿函数处理key值不能取模无法映射 --- BKDRHash 三、开…

【Linux系列P4】Linux需要什么?编辑器?软件包?一文帮你了解掌握 [yum][vim]———基础开发工具篇

前言 大家好,这里是YY的Linux系列part4;本章主要内容面向接触过Linux的老铁,主要内容含【学习yum工具,进行软件安装】【拓展yum源安装】【掌握vim编辑器使用,基本命令】【命令集】【懒人配置文件安装教程】 在下一章节…

Java高并发编程—可见性与有序性原理

原子性、可见性和有序性是并发编程所面临的三大问题。 Java通过CAS操作已解决了并发编程中的原子性问题,本章为大家介绍Java如何解决剩余的另外两个问题——可见性和有序性。 CPU物理缓存结构 由于CPU的运算速度比主存(物理内存)的存取速度…

Android系统原理性问题分析 - 多路并发情况下的C/S模型

声明 在Android系统中经常会遇到一些系统原理性的问题,在此专栏中集中来讨论下。Android系统中很多地方都采用了I/O多路复用的机制,为了引出I/O多路复用机制,先来分析多路并发情况下的C/S模型。此篇参考一些博客和书籍,代码基于A…

C++条件变量condition_variable

一、问题 假设没有条件变量,对于一个生产者消费者问题,消费线程在得知队列中没有产品时,将阻塞自己。生产者线程可以给队列中放入产品,但是没有办法激活消费者线程,而消费者线程处于阻塞状态也没有办法自己激活自己。…