二叉树链式结构的实现-二叉树的前序 中序 后序 层序遍历

news2024/9/20 1:01:32

一、二叉树的结构了解

二叉树是:

  1. 空树
  2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

前序: 根 左子树 右子树 --》先根
中序:左子树 根 右子树 --》中根
后序:左子树 右子树 根 --》后根
层序:一层一层访问

image.png

二、二叉树的构建

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	node->data = x;
	node->left = NULL;
	node->right = NULL;
	return node;
}

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a,int* pi)//pi访问下标
{
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}

	BTNode* root = BuyNode(a[*pi]);
	(*pi)++;

	root->left = BinaryTreeCreate(a, pi);
	root->right = BinaryTreeCreate(a, pi);
	return root;
}

三、二叉树的遍历

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

(一)前序、中序以及后序遍历

二叉树的遍历有前序/中序/后序的递归结构遍历

1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树**。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。**

举例:先序遍历

image.png

(二)计算二叉树的结点个数

二叉树的结点个数

//int size = 0;//全局变量

//二叉树结点个数--遍历计数
int BTreeSize(BTNode* root)
{

	/*if (root->data == NULL)
	{
		return size;//全部变量
	}
	++size;
	BTreeSize(root->left);
	BTreeSize(root->right);
	return size;*/

	return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
}

叶子结点个数

//叶子结点个数    (完全二叉树才能只看左边)
int BTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left == NULL && root->right==NULL)
	{
		return 1;
	}
	return BTreeLeafSize(root->left)
		+ BTreeLeafSize(root->right);
}

求二叉树的高度


// 求二叉树的高度

//方法一
//int BTreeHeight(BTNode* root)
//{
//	if (root == NULL)
//		return 0;
//
//	return BTreeHeight(root->left) > BTreeHeight(root->right)
//		? BTreeHeight(root->left) + 1 : BTreeHeight(root->right) + 1;
//}
//方法一:只知道left和right哪个大,然后再计算了一次大的量+1
//注意考虑时间复杂度

int BTreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;

	int leftHeight = BTreeHeight(root->left);
	int rightHeight = BTreeHeight(root->right);

	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}

第K层的结点个数

转换成左子树的第k-1层和右子树的第k-1层

image.png

int BTreeLevrelKSize(BTNode* root, int k)
{
	assert(k > 0);

	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}

	return BTreeLevelKSize(root->left, k - 1) + BTreeLevrelKSize(root->right, k - 1);
}

二叉树查找值为x的结点

//二叉树查找值为 x的结点

BTNode* BTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;

	BTNode* left =  BTreeFind(root->left, x);
	if (!left)
		return left;

	BTNode* right = BTreeFind(root->right, x);
	if (!right)
		return right;
	return NULL;
}

(三)层序遍历

层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历(一层一层访问)。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
image.png
创建一个队列的queue.h queue.c略

#include "quue.h"
void LevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);

	if(root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ", front->data);

		if(front->left)
			QueuePush(&q, front->left);

		if(front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");
	QueueDestroy(&q);
}

int main()
{
	BTNode* root = CreatBinaryTree();
	LevelOrder(root);
	return 0;
}

判断二叉树是否是完全二叉树

// 判断二叉树是否是完全二叉树
int 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;
}

四、二叉树的销毁

//后序
void TreeDestory(root)
{
    if(root == NULL)
        return;
    TreeDestory(root->left);
    TreeDestory(root->right);
    free(root);
}

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

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

相关文章

命理八字之答案之书前端uniapp效果实现

#uniapp# #答案之书# 不讲废话&#xff0c;先上截图 <div class"padding"><div class"flex align-center justify-center" style"padding-top:100px;"><div class"radarContainer"><div id"radarBox"…

C#医学实验室/检验信息管理系统(LIS系统)源码

目录 检验系统的总体目标 LIS主要包括以下功能&#xff1a; LIS是集&#xff1a;申请、采样、核收、计费、检验、审核、发布、质控、耗材控制等检验科工作为一体的信息管理系统。LIS系统不仅是自动接收检验数据&#xff0c;打印检验报告&#xff0c;系统保存检验信息的工具&a…

关于Android绘制这一遍就够了

Android绘制基础 Android平台提供了一套完整的UI框架&#xff0c;其中包括了绘制组件和绘制API。在Android中&#xff0c;绘制主要涉及到两个核心概念&#xff1a;Canvas和Paint。 Canvas Canvas是Android中的一个类&#xff0c;它代表了绘图的画布。你可以在这个画布上进行…

CAS Client使用以及执行原理

CAS Client使用以及执行原理 流程介绍 CAS Client是利用Java Web中的Filter进行实现认证功能&#xff0c;客户端对CAS Server的认证流程分为以下步骤&#xff1a; 访问CAS Client服务 由于当前session中未检测到认证信息&#xff0c;会重定向到CAS Server地址进行认证 在CA…

11.Ribbon负载均衡策略及修改

ZoneAvoidanceRule 默认使用的规则 修改规则 第一种方式&#xff1a;定义IRule的Bean,作用于全局。 SpringBootApplication MapperScan("com.xkj.org.mapper") public class OrderApplication {public static void main(String[] args) {SpringApplication.run(Ord…

设计模式——2_A 访问者(Visitor)

文章目录 定义图纸一个例子&#xff1a;如何给好奇宝宝提供他想知道的内容菜单、菜品和配方Menu(菜单) & Cuisine(菜品)Material(物料、食材) 产地、有机蔬菜和卡路里Cuisine & Material 访问者VisitorCuisine & Material 碎碎念访问者和双分派访问者和代理写在最后…

C#基础|StringBuilder字符串如何高效处理。

哈喽&#xff0c;你好&#xff0c;我是雷工。 字符串处理在C#程序开发中是使用频率比较高的&#xff0c;但常规的字符串处理方式对内存占用比较多&#xff0c;为了优化内存&#xff0c;减少不必要的内存浪费&#xff0c;引入了StringBuilder类。 下面学习下StringBuilder类的使…

插入排序动态展示3(Python可视化源代码)

修改了“开始”命令按钮&#xff0c;每次单击“开始”&#xff0c;都重新排序。 Python代码 import tkinter as tk import random import timeclass InsertionSortVisualizer:def __init__(self, root, canvas_width800, canvas_height400, num_bars10):self.root rootself.…

wasm 系列之 WebAssembly 和 emscripten 暴力上手

wasm 是什么&#xff1f; wasm 是 WebAssembly 的缩写。wasm 不是传统意义上的汇编语言&#xff0c;而是一种编译的中间字节码&#xff0c;可以在浏览器和其他 wasm runtime 上运行非 JavaScript 类型的语言&#xff0c;只要能被编译成 wasm&#xff0c;譬如 kotlin/wasm、Rus…

鸿蒙OpenHarmony【轻量系统编写“Hello World”程序】 (基于Hi3861开发板)

编写“Hello World”程序 下方将通过修改源码的方式展示如何编写简单程序&#xff0c;输出“Hello world”。请在下载的源码目录中进行下述操作。 前提条件 已参考鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到…

编写函数fun,它的功能是:根据以下公式求P的值,结果由函数值带回。m与n为两个正整数且要求m>n

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 编写…

【JavaEE初阶系列】——网络层IP协议(地址管理和路由选择)

目录 &#x1f6a9;网络层 &#x1f388;IP协议 &#x1f469;&#x1f3fb;‍&#x1f4bb;IP协议"拆包组包"功能 &#x1f388;地址管理 &#x1f469;&#x1f3fb;‍&#x1f4bb;IP地址的分类 &#x1f469;&#x1f3fb;‍&#x1f4bb;NAT机制如何工作的…

记录:阿里云服务器网站搭建(2)

Docker安装Mysql mysql版本 查看开发环境中mysql版本 &#xff1a;select version()&#xff1b;安装时版本尽量保证一致&#xff0c;最低要求大版本要一致 docker 拉取mysql镜像 docker pull mysql:8.0.36 docker启动mysql容器 docker run -d \ # 创建并运行一个容器&…

下班族张亮的副业赚钱故事

张亮是一个普通的上班族&#xff0c;每天过着朝九晚五的生活。他渴望改变现状&#xff0c;却又觉得生活缺乏突破口。直到有一天&#xff0c;他在网络上偶然发现了水牛社这个平台&#xff0c;这为他打开了一扇新的大门。 张亮开始利用下班后的空闲时间&#xff0c;认真浏览水牛社…

IDEA下载与安装

1.下载 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;7v5q 2.安装

综合案例(前端代码练习):猜数字和表白墙

目录 一、猜数字 html代码&#xff1a; 点击 猜 按钮的js代码&#xff1a; 点击 重开游戏 按钮的js代码&#xff1a; 整体代码&#xff1a; 页面效果&#xff1a; 二、留言板 css代码&#xff1a; html代码&#xff1a; js代码&#xff08;主逻辑在这&#xff09;&am…

JAVA高阶私房菜:JVM虚拟机核心概念及参数微调实验

目录 基础快速掌握 什么是JVM虚拟机 JVM的的实现 操作系统-虚拟机-JRE-JDK的关系 生产环境部署JDK还是JRE JVM内存组成部分和堆空间分布 内存组成 堆空间内存分布 内存分布 堆空间分配 JVM堆空间垃圾回收流程及JVM参数 垃圾回收流程 JVM参数分类 JVM参数格式分类 …

山东大学操作系统实验一(Linux虚拟机实现)

目录 实验题目 实验要求 示例程序 主程序 头文件 重点代码解析 一、main函数的参数 参数介绍 参数输入方式 本块代码 二、信号处理 本块代码 原理介绍 实现效果 三、kill函数 功能介绍 使用方式 本块代码 四、头文件处理 本块代码 代码作用 实验程序 …

Python数据可视化:频率统计条形图countplot()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 Python数据可视化&#xff1a; 频率统计条形图 countplot() [太阳]选择题 请问关于以下代码表述正确的选项是&#xff1f; import seaborn as sns import matplotlib.pyplot as plt data { …

二、python+前端 实现MinIO分片上传

python前端 实现MinIO分片上传 一、背景二、流程图三、代码 一、背景 问题一&#xff1a;前端 -> 后端 ->对象存储 的上传流程&#xff0c;耗费带宽。 解决方案&#xff1a;上传流程需要转化为 前端 -> 对象存储&#xff0c;节省上传带宽 问题二&#xff1a;如果使用…