【数据结构 06】二叉树

news2024/11/23 21:07:10

一、原理

二叉树算法核心思维:递归

满二叉树:二叉树的层数为K,节点数为2^K - 1

完全二叉树:二叉树的层数为K,前K-1层是满的,第K层是连续的

满二叉树是完全二叉树的子集。

任意二叉树:若叶子节点的个数是n_o,设度为2(有2个子节点)的节点个数是n_2,则n_0 = n_2 + 1

二叉树的第i层上最多有2^{i-1}个节点,第n个节点的满二叉树深度h = \lg (n+1)

二叉树可以顺序存储或链式存储。

二、BinaryTree.h

#define _CRT_SECURE_NO_WARNINGS 1

#pragma
#include <iostream>
#include <string>
#include <cassert>
using namespace std;

typedef char DataType;

struct BinaryTreeNode
{
	DataType data;
	BinaryTreeNode* left;
	BinaryTreeNode* right;

	BinaryTreeNode(DataType x)
		: data(x), left(nullptr), right(nullptr)
	{}
};

class BinaryTree
{
	typedef BinaryTreeNode Node;
public:
	// 构建,指定构造数据序列
	void Create(const DataType* datas, int& i)
	{
		_root = _Create(datas, i);
	}

	// 先序遍历(根、左、右)
	void PreOrder()
	{
		_PreOrder(_root);
		cout << ",先序遍历结束" << endl;
	}

	// 中序遍历
	void InOrder()
	{
		_InOrder(_root);
		cout << ",中序遍历结束" << endl;
	}

	// 后序遍历
	void PastOrder()
	{
		_PastOrder(_root);
		cout << ",后序遍历结束" << endl;
	}

	// 总节点数
	int Size()
	{
		int num = 0;
		_Size(_root, num);
		return num;
	}

	// 叶子节点数
	int LeafSize()
	{
		int leafNum = 0;
		_LeafSize(_root, leafNum);
		return leafNum;
	}

	// 深度(层数)
	int Depth()
	{
		return _Depth(_root);
	}

	// 子树数量
	int TreeSize()
	{
		return _TreeSize(_root);
	}

	// 销毁
	void Destroy()
	{
		_Destroy(_root);
		_root = nullptr;
		cout << "二叉树销毁成功" << endl;
	}

private:
	Node* _Create(const DataType* datas, int& i)
	{
		if (datas[i] == '#')
			return nullptr;

		Node* root = new Node(datas[i]);
		root->left = _Create(datas, ++i);
		root->right = _Create(datas, ++i);
		return root;
	}

	void _PreOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		cout << root->data << ' ';
		_PreOrder(root->left);
		_PreOrder(root->right);
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		_InOrder(root->left);
		cout << root->data << ' ';
		_InOrder(root->right);
	}

	void _PastOrder(Node* root)
	{
		if (root == nullptr)
		{
			cout << "# ";
			return;
		}

		_PastOrder(root->left);
		_PastOrder(root->right);
		cout << root->data << ' ';
	}

	void _Size(Node* root, int& num)
	{
		if (root == nullptr)
			return;

		++num;
		_Size(root->left, num);
		_Size(root->right, num);
	}

	void _LeafSize(Node* root, int& leafNum)
	{
		if (root == nullptr)
			return;

		if (root->left == nullptr && root->right == nullptr)
			leafNum++;
		_LeafSize(root->left, leafNum);
		_LeafSize(root->right, leafNum);
	}

	int _Depth(Node* root)
	{
		if (root == nullptr)
			return 0;

		int leftDepth = _Depth(root->left);
		int rightDepth = _Depth(root->right);

		return (leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1);
	}

	int _TreeSize(Node* root)
	{
		if (root == nullptr)
			return 0;

		return (root->left == nullptr && root->right == nullptr) ? 0 :
			_TreeSize(root->left) + _TreeSize(root->right) + 1;
	}

	void _Destroy(Node* root)
	{
		if (root == nullptr)
			return;
		
		_Destroy(root->left);
		_Destroy(root->right);
		cout << root->data << "销毁,";
		delete root;
	}

private:
	Node* _root;
};

三、test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "BinaryTree.h"

int main()
{
	cout << "--Test1---" << endl << "数据序列: 123###45##6##" << endl;
	BinaryTree bt;

	// 构建二叉树
	int i = 0;
	bt.Create("123###45##6##", i);
	bt.PreOrder();
	bt.InOrder();
	bt.PastOrder();

	// 计算二叉树节点总数
	cout << "二叉树节点总数为:" << bt.Size() << endl; // 6

	// 计算二叉树叶子结点数
	cout << "二叉树叶子结点数为:" << bt.LeafSize() << endl; // 3

	// 计算二叉树深度
	cout << "二叉树深度:" << bt.Depth() << endl; // 3

	// 计算二叉树子树数量
	cout << "二叉树子树数量:" << bt.TreeSize() << endl; // 3

	// 销毁二叉树
	bt.Destroy(); // 3销毁,2销毁,5销毁,6销毁,4销毁,1销毁,二叉树销毁成功

	// 计算二叉树节点总数
	cout << "二叉树节点总数为:" << bt.Size() << endl;

	return 0;
}

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

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

相关文章

NC248:左叶子之和(C++)

1.题目描述 2.题目分析 我们以一个二叉树为例 左叶子的特点是什么&#xff1f; 是左节点并且没有左右孩子节点 所以我们用leftnode保存root->lefe节点&#xff0c;判断条件为leftnode存在&#xff0c;并且不存在leftnode->left和leftnode->right&#xff0c;如果满…

事务、MVCC、锁

目录 事务MVCC锁 事务 四大特性&#xff1a;ACID 脏读&#xff1a;事务A读取到未提交事务B修改的数据 不可重复读&#xff1a;事务A修改了未提交事务B读取的数据 幻读&#xff1a;事务A增删了未提交事务B读取的数据 不可重复读与幻读都是读取的结果不同&#xff0c;前者侧重于…

常用芯片学习——CD4094芯片

CD4094 8位移位寄存器/3态输出缓冲器 使用说明 CD4094是由一个 8 位串行移位寄存器和一个 3 态输出缓冲器组成的 CMOS 集成电路。寄存器带有存储锁存功能&#xff0c;集成电路根据 STROBE 信号确定锁存器是否接收移位寄存器各位数据&#xff0c;数据是否由锁存器传输到 3 态输…

单元测试 | Junit4“单元测试“ ( Java中可用 )

目录: 使用JUnit4进行“单元测试” 作者简介 &#xff1a;一只大皮卡丘&#xff0c;计算机专业学生&#xff0c;正在努力学习、努力敲代码中! 让我们一起继续努力学习&#xff01; 文章用于本人学习使用 &#xff0c; 同时希望能帮助大家。 欢迎大家点赞&#x1f44d; 收藏⭐ …

HarmonyOS 鸿蒙驱动消息机制管理

驱动消息机制管理 使用场景 当用户态应用和内核态驱动需要交互时&#xff0c;可以使用HDF框架的消息机制来实现。 接口说明 消息机制的功能主要有以下两种&#xff1a; 用户态应用发送消息到驱动。 用户态应用接收驱动主动上报事件。 表1 消息机制接口 方法描述struct …

扩展学习|商业智能和大数据分析的研究前景(比对分析)

文献来源&#xff1a; Liang T P , Liu Y H .Research Landscape of Business Intelligence and Big Data analytics: A bibliometrics study[J].Expert Systems with Applications, 2018, 111(NOV.):2-10.DOI:10.1016/j.eswa.2018.05.018. 信息和通信技术的快速发展导致了数字…

【LVGL源码移植环境搭建】

LVGL源码移植&环境搭建 ■ LVGL源码移植■ 下载LVGL源码■ 修改LVGL文件夹■■■■ 视频链接 Ubuntu模拟器环境建置 ■ LVGL源码移植 ■ 下载LVGL源码 LVGL源码 我们以选择v8.2.0为例&#xff0c;选择8.2.0下载 ■ 修改LVGL文件夹 1.我们只需要关注这5个文件即可&…

公司在数字化过程中犯的7个错误,及其解决方法

今天&#xff0c;大多数公司都意识到技术提供了转变其业务模式和产品的机会。但是&#xff0c;没有多少人知道他们在采用时所犯的错误。 既然我们现在都同意数字化转型不是一种选择&#xff0c;我们不妨拥抱变化并学习如何最好地采用它。但说起来容易做起来难&#xff0c;不是…

网页版idea、pycharm搭建

官网教程提供了两种方法&#xff1a;1、有给应用版idea或pycharm安装插件来开放网页服务&#xff1b;2、使用docker创建容器开放网页服务。这边推荐并介绍第二种步骤。 基本过程为&#xff1a;拉取相关镜像&#xff1b;开启服务&#xff1b;使用网页版 &#xff08;细节和注意点…

目标检测算法训练数据准备——Penn-Fudan数据集预处理实例说明(附代码)

目录 0. 前言 1. Penn-Fudan数据集介绍 2. Penn-Fudan数据集预处理过程 3. 结果展示 4. 完整代码 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准确的地方。如…

Python爬虫获取淘宝商品详情页数据|实现自动化采集商品信息

近年来&#xff0c;随着互联网的发展&#xff0c;越来越多的数据以网页的形式存在于各个网站上。对于数据分析师、研究员或者仅仅是对数据感兴趣的人来说&#xff0c;如何高效地提取和分析网页数据成为了一项重要的技能。Python作为一门强大的编程语言&#xff0c;通过其丰富的…

【pytorch】nn.linear 中为什么是y=xA^T+b

我记得读教材的时候是yWxb, 左乘矩阵W&#xff0c;这样才能表示线性变化。 但是pytorch中的nn.linear中&#xff0c;计算方式是yxA^Tb&#xff0c;其中A是权重矩阵。 为什么右乘也能表示线性变化操作呢&#xff1f;因为pytorch中&#xff0c;照顾到输入是多个样本一起算的&…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

使用ChatGPT学习大象机器人六轴协作机械臂mechArm

引言 我是一名机器人方向的大学生&#xff0c;近期学校安排自主做一个机器人方面相关的项目。学校给我们提供了一个小型的六轴机械臂&#xff0c;mechArm 270M5Stack&#xff0c;我打算使用ChatGPT让它来辅助我学习如何使用这个机械臂并且做一个demo。 本篇文章将记录我是如何使…

Windows编程入门-窗口控件-资源操作

window控件&#xff1a; 控件是常见的窗口上的交互元素例如&#xff1a;一个按钮&#xff0c;一个复选框&#xff0c;一个列表框等。 当控件的特定功能被触发后&#xff0c;会主动发送消息通知父窗口&#xff0c;父窗口可以通过发送消息给控件控制控件的行为。 控件的本质是一个…

使用visual studio写一个简单的c语言程序

官网下载visual studio&#xff0c;社区版免费的 https://visualstudio.microsoft.com/zh-hans/ 下载好以后选择自己的需求进行安装&#xff0c;我选择了两个&#xff0c;剩下的是默认。 创建文件&#xff1a;

Linux编辑器之vim的使用

文章目录 一、vim简介二、vim的基本概念三、vim的基本操作四、vim正常模式命令集移动光标删除文字复制替换撤销上一次操作更改跳至指定的行vim末行模式命令集列出行号跳到文件中的某一行查找字符保存文件离开vim 五、进阶vim玩法打开文件批量注释代码执行shell命令指定注释窗口…

如何判断 LM358 芯片是否损坏或故障?

LM358 芯片是一种流行的低功耗双运放&#xff0c;广泛应用于各种电子电路中&#xff0c;包括放大器、滤波器、积分器、比较器等。它以其低成本、高性价比和广泛的工作电源范围&#xff08;3V至32V单电源或1.5V至16V双电源&#xff09;而被广泛使用。 然而&#xff0c;像所有电…

怎么查询鸿蒙真机支持的API版本

1、打开设备的开发者模式与USB调试并通过USB连接上电脑。 2、管理员身份运行cmd。 3、进入hdc.exe所在目录。(鸿蒙OS IDE的SDK下载目录中) 4、输入hdc shell&#xff0c;进入特殊模式 5、输入 getprop hw_sc.build.os.apiversion 查看API版本 6、输入 getprop hw_sc.build…

盘点Python网页开发轻量级框架Flask知识

目录 一、Flask框架概述 二、核心组件 1、WSGI服务器 2、Jinja2模板引擎 3、URL路由 4、数据库集成 三、应用场景 博客平台 内容管理系统&#xff08;CMS&#xff09; API开发 四、优缺点 优点&#xff1a; 缺点&#xff1a; 五、总结 随着Web开发的日益普及&…