二叉树详解-第四篇 二叉树链式结构的实现

news2024/9/19 10:09:39


目录

1.二叉树的遍历

1.1前序遍历:

1.2 中序遍历:

1.3 后序遍历:

2.二叉树链式结构的实现

2.1 Tree.h

2.2 Tree.cpp

2.2.1 前序遍历 void PreOrder(TNode* Root)

2.2.2 中序遍历 void InOrder(TNode* Root)

2.2.3 后序遍历 void BacOrder(TNode* Root)

2.2.4 求树的总节点数 int Treesize(TNode* root)

2.2.5 求叶子结点数 int Leafsize(TNode* root)

2.2.6 求树的高度 int Treeheight(TNode* root)

2.2.7 求二叉树第K层节点数 int Knum(TNode* root,int k)

2.2.8 查找节点为x值所在节点指针 TNode* Treefind(TNode* root, TreeType x)


1.二叉树的遍历

前序遍历:根 左子树 右子树

中序遍历:左子树 根 右子树

后序遍历:左子树 右子树 根

1.1前序遍历:

(根左右)

                                

                        图1                                                                              图2

首先我们要把所有子树空的地方写上N(代表NULL),如图2。

1.首先从1开始出发,1作为根,2是1的左子树,4是1的右子树,输出1,然后进入2。

遍历序列:1 

2. 进入2后,2作为根,3作为2的左子树,N作为2的右子树,输出2,然后进入3。

遍历序列:1 2

3.进入3后,3作为根,N为3的左子树,N为3的右子树,输出3,然后进入左子树的N。

遍历序列:1 2 3

4.进入N后,遇到了N,就输出N,并返回到根(3)。

遍历序列:1 2 3 N

5.返回3后,根和左子树都已经输出,进入右子树的N。同时遇到了N打印并返回。

遍历序列:1 2 3 N N

6.再次返回到了3,根 左子树 右子树 都已经输出了,所以再次返回3的根(2)。返回2后,2作为根,2的左子树已经输出,所以进入2的右子树(N),因为右子树为N,所以输出N即可。

遍历序列:1 2 3 N N N

7. 2作为根,2的左子树右子树有已经输出了,返回2的根(1)。返回1后,1作为根,1的左子树已经输出,直接进入1的右子树(4)即可,进入4后,4作为根,先输出4,然后在进入4的左子树。

遍历序列:1 2 3 N N N 4

8.进入5后,5作为根,所以先输出5,然后进入5的左子树,左子树为N,输出N,然后进入5的右子树,右子树也为N,输出N。

遍历序列:1 2 3 N N N 4 5 N N 

9. 5和他的左子树右子树都已经输出,此时返回到5的根(4),4作为根,4的左子树已经输出,此时进入4的右子树(6) ,进入6后,6作为根,先输出6;输出6后进入6的左子树,左子树为N,输出N。然后进入6的右子树,右子树为N,输出N。

遍历序列:1 2 3 N N N 4 5 N N 6 N N

1.2 中序遍历:

(左根右)

                                 

                        图1                                                                              图2

1.首先进入1,1作为根,由于是左跟右,所以还不能输出1,要先进入1的左子树(2),进入2后,2作为根,还要进入2的左子树(3),进入3后,3作为根,要先进入3的左子树(N),3的左子树为N,直接输出N,输出N后,左子树已经输出,3作为根,此时可以输出3,3输出后,在进入3的右子树,3的右子树为N,输出N即可。

遍历序列:N 3 N 

2. 3作为根的子树已经全部输出,此时返回到3的根(2),2作为根,2的左子树(3)已经输出,此时输出根(2),输出根后,再输出2的右子树(N),右子树为N,直接输出N。

遍历序列:N 3 N 2 N 

3. 2作为根的子树已经全部输出,此时返回到2的根(1),1作为根,1的左子树(2)已经输出,此时输出根(1),输出根后,再进入右子树(4),4作为根,要先进入4的左子树(5),5作为根,5的左子树为N,直接输出N,输出N后再输出根(5),输出5,输出5后再进入5的右子树(N),输出N;

遍历序列:N 3 N 2 N 1 N 5 N 

4.  5的子树全部输出,此时返回到5的根(4),4作为根,4的左子树(5)输出,此时可以输出根(4),输出根后,再进入根的右子树(6),6作为根,要先进入6的左子树,左子树为N,输出N,然后返回到根(6),此时输出根(6),输出根后,进入6的右子树,右子树为N,输出N。

遍历序列:N 3 N 2 N 1 N 5 N 4 N 6 N

1.3 后序遍历:

(左右根)

                                 

                        图1                                                                              图2

1.首先进入1,1作为根,先进入1的左子树(2),2作为根,先进入2的左子树(3),3作为根,先进入3的左子树(N),输出N并返回到根(3),再进入3的右子树(N),输出N并返回到根(3),3作为根,3的左子树和右子树都已经输出,所以此时输出3,输出3后返回到3的根(2)。

遍历序列:N N 3

2. 进入2后,2作为根,2的左子树已经输出,再进入2的右子树,2的右子树为N, 输出N并且返回到根,2作为根,2的左子树和右子树都已经输出,此时可以输出根(2),输出2并且返回2的根(1)。

遍历序列:N N 3 N 2 

3.进入1后,1作为根,1的左子树已经输出,再进入1的右子树(4),4作为根,先进入4的左子树(5),5作为根,先进入5的左子树(N),左子树为N,输出N并且返回到根(5),5作为根,再进入5的右子树,5的右子树为N,输出N并返回到根,5的左子树和右子树都已经输出,此时输出5并且返回到5的根(4)。

遍历序列:N N 3 N 2 N N 5

4. 进入4后,4作为根,4的左子树已经输出,进入4的右子树(6),6左右根,先进入6的左子树N,输出N并返回到根,再进入6的右子树N,输出N并返回到根。6作为根,其左子树和右子树都已经输出,此时输出6并且返回到6的根(4),4作为根,4的左子树和右子树都已经输出,此时输出4并且返回到4的根(1)。

遍历序列:N N 3 N 2 N N 5 N N 6 4

5.进入1后,1作为根,1的左子树和右子树都已经输出,此时输出1。

遍历序列:N N 3 N 2 N N 5 N N 6 4 1


2.二叉树链式结构的实现

2.1 Tree.h

源码:

#define _CRT_SECURE_NO_WARNINGS 1

#pragma once
#include<iostream>
#include<algorithm>
using namespace std;

typedef int TreeType;

typedef struct Tree
{
	TreeType val;
	struct Tree* left;
	struct Tree* right;
}TNode;

void PreOrder(TNode* root);//前序遍历
void InOrder(TNode* Root);//中序遍历
void BacOrder(TNode* Root);//后序遍历
int Treesize(TNode* root);//求节点数
int Leafsize(TNode* root);//求叶子节点数
int Treeheight(TNode* root);//求树高度
int Knum(TNode* root, int k);//第K层结点数
TNode* Treefind(TNode* root, TreeType x);//查找节点为x值所在节点指针

2.2 Tree.cpp

源码:

#include"Tree.h"




void PreOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	cout << Root->val << " ";
	PreOrder(Root->left);
	PreOrder(Root->right);

}



void InOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	InOrder(Root->left);
	cout << Root->val << " ";
	InOrder(Root->right);

}


void BacOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	BacOrder(Root->left);
	BacOrder(Root->right);
	cout << Root->val << " ";
}


int Treesize(TNode* root)//求节点数
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return Treesize(root->left) + Treesize(root->right) + 1;
	}

}

int Leafsize(TNode* root)//求叶子节点数
{
	if (root == NULL) {
		return 0;
	}
	if (root->left == root->right == NULL) {
		return 1;
	}
	return Leafsize(root->left) + Leafsize(root->right);

}

int Treeheight(TNode* root)//求树高度
{
	if (root == NULL) {
		return 0;
	}
	int leftnum = Treeheight(root->left);
	int rightnum = Treeheight(root->right);


	return leftnum > rightnum ? leftnum + 1 : rightnum + 1;

}

int Knum(TNode* root,int k)//二叉树第k层节点个数
{

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

	return Knum(root->left,k-1) + Knum(root->right,k-1);

}


TNode* Treefind(TNode* root, TreeType x)//查找节点为x值所在节点指针
{
	if (root == NULL) {
		return NULL;
	}
	if (root->val == x) {
		return root;
	}

	TNode* ret1 = Treefind(root->left, x);
	if (ret1) {
		return ret1;
	
	}

	TNode* ret2 = Treefind(root->right, x);
	if (ret2) {
		return ret2;

	}
	return NULL;

}

2.2.1 前序遍历 void PreOrder(TNode* Root)

void PreOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	cout << Root->val << " ";
	PreOrder(Root->left);
	PreOrder(Root->right);

}

1.先输出节点的值,再进行左子树遍历和右子树遍历

2.2.2 中序遍历 void InOrder(TNode* Root)

void InOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	InOrder(Root->left);
	cout << Root->val << " ";
	InOrder(Root->right);

}

1.先递归左子树,在输出节点值,再递归右子树。

2.2.3 后序遍历 void BacOrder(TNode* Root)

void BacOrder(TNode* Root)
{
	if (Root == NULL)
	{
		cout << "N ";
		return;
	}
	BacOrder(Root->left);
	BacOrder(Root->right);
	cout << Root->val << " ";
}

1.先递归左子树和右子树,最后输出节点值。

2.2.4 求树的总节点数 int Treesize(TNode* root)

int Treesize(TNode* root)//求节点数
{
	if (root == NULL)
	{
		return 0;
	}
	else
	{
		return Treesize(root->left) + Treesize(root->right) + 1;
	}

}

1.如果遇到空节点(N),就返回0,其余情况返回左右子树递归+1。

2.2.5 求叶子结点数 int Leafsize(TNode* root)

int Leafsize(TNode* root)//求叶子节点数
{
	if (root == NULL) {
		return 0;
	}
	if (root->left == root->right == NULL) {
		return 1;
	}
	return Leafsize(root->left) + Leafsize(root->right);

}

1.遇到空节点就返回0。

2.叶子节点的特点是其左右孩子都为空,则当if (root->left == root->right == NULL)成立时,返回1.

3.其余情况返回左子树递归+右子树递归。

2.2.6 求树的高度 int Treeheight(TNode* root)

int Treeheight(TNode* root)//求树高度
{
	if (root == NULL) {
		return 0;
	}
	int leftnum = Treeheight(root->left);
	int rightnum = Treeheight(root->right);


	return leftnum > rightnum ? leftnum + 1 : rightnum + 1;

}

1.当为空节点时,返回0。

2.用leftnum存储左子树的层数,用rightnum存储右子树的层数,两者返回最大者+1.

2.2.7 求二叉树第K层节点数 int Knum(TNode* root,int k)

int Knum(TNode* root,int k)//二叉树第k层节点个数
{

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

	return Knum(root->left,k-1) + Knum(root->right,k-1);

}

1.如果时空节点,则返回0。

2.当k==1时,则此时在第K层的某个节点上,则返回1即可。

3.其余情况返回Knum(root->left,k-1) + Knum(root->right,k-1)。

2.2.8 查找节点为x值所在节点指针 TNode* Treefind(TNode* root, TreeType x)

TNode* Treefind(TNode* root, TreeType x)//查找节点为x值所在节点指针
{
	if (root == NULL) {
		return NULL;
	}
	if (root->val == x) {
		return root;
	}

	TNode* ret1 = Treefind(root->left, x);
	if (ret1) {
		return ret1;
	
	}

	TNode* ret2 = Treefind(root->right, x);
	if (ret2) {
		return ret2;

	}
	return NULL;

}

1.如果当前节点的值等于要查找的值,则返回该节点的地址。

2.用ret1和ret2接收Treefind(root->left, x)的返回值和Treefind(root->right, x)的返回值,如果其中有一个不为空指针,则说明找到了,就立马返回这个地址。

3.其余情况返回NULL即可。


本篇完

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

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

相关文章

Linux中断框架

不管是裸机实验还是 Linux 下的驱动实验&#xff0c;中断都是频繁使用的功能&#xff0c;在裸机中使用中断我们需要做一大堆的工作&#xff0c;比如配置寄存器&#xff0c;使能 IRQ 等等。Linux 内核提供了完善的中断框架&#xff0c;我们只需要申请中断&#xff0c;然后注册中…

【rockyLinux】rockyLinux 9.4 安装 java jdk

一、安装 java 1.选择版本 yum list | grep jdk各个版本之间的区别&#xff1a; 2.选择了&#xff1a;java-17-openjdk-devel.x86_64&#xff08;开发者版本&#xff09;&#xff0c;开始安装 建议安装在 /usr/local 这个目录下&#xff0c;可以创建一个 app 目录来收录它…

重生奇迹MU 三个阶段三种体验

重生奇迹MU的玩家们通常按等级分为三个阶段。在这三个不同的阶段里&#xff0c;游戏中的玩家好像深入了三个不同的世界&#xff0c;经历了三种不同的游戏体验&#xff0c;收获了三种不同的精彩&#xff01; 从刚开始游戏一直到达到400级&#xff0c;是游戏中的第一个阶段&…

0719_驱动3 printk使用方法

一、printk使用方法 1.应用层打印使用printf&#xff0c;内核层使用printk 2.如何查看内核层中printk如何使用 3.在内核空间执行grep "printk" * -nR 4.在内核空间执行vi -t KERN_INFO 5.printk有8中打印级别&#xff08;0-7&#xff09;&#xff0c;打印级别用来过滤…

暴雨宅家?AI拯救你的无聊暑假!高中生必藏神器大公开

嘿&#xff0c;各位高中生朋友们&#xff0c;最近是不是被这没完没了的暴雨困在家里&#xff0c;感觉暑假生活都快发霉了&#xff1f;别急&#xff0c;今天我要揭秘一个宝藏网站—— ai123.cn&#xff0c;它简直就是咱们暑期宅家必备的救星&#xff01;接下来&#xff0c;我就来…

Selenium相对定位

测试网站&#xff1a;Web form 相对定位的方法&#xff1a; above()&#xff1a;定位基准元素上方的元素below()&#xff1a;定位基准元素下方的元素to_left_of()&#xff1a;定位基准元素左侧的元素to_right_of()&#xff1a;定位基准元素右侧的元素near() &#xff1a;定位基…

Windows横向渗透

准备靶机windows&#xff1a;192.168.10.131 准备攻击机&#xff1a;192.168.10.130 1.用cs连接到了windows靶机 2.使用cs探测内网信息&#xff1a; 查看当前目标系统网络情况&#xff0c;确认目标系统所在内网网段为10段 3.使用cs的portscan功能对内网进行扫描 portscan 1…

aarch64环境安装minio

1.去官网查看最新版本 MinIO | 用于AI的S3 & Kubernetes原生对象存储 2.使用命令安装,采取wget和dnf安装 wget https://dl.min.io/server/minio/release/linux-arm64/archive/minio-20240113075303.0.0-1.aarch64.rpm -O minio.rpm sudo dnf install minio.rpm 注意点…

MATLAB学习日志DAY16

16.数组类型&#xff08;1&#xff09; 16.1多维数组 MATLAB 环境中的多维数组是具有多个下标的数组。创建多维数组的一种方法是调用具有多个参数的 zeros、ones、rand 或 randn。 R randn(3,4,5); 创建一个 345 数组&#xff0c;共包含 3*4*5 60 个正态分布的随机元素。…

springboot在加了mapper之后报错

springboot在加了mapper之后报错 最后发现是spring boot版本不兼容&#xff0c;spring-boot-starter-parent换成3.0.5之后可以了

大模型金九银十秋招:AI时代的就业新趋势,收藏我这篇就够了非常详细

随着人工智能技术的飞速发展&#xff0c;大模型&#xff08;Large Models&#xff09;在各个领域的应用日益广泛&#xff0c;从自然语言处理到图像识别&#xff0c;从自动驾驶到智能推荐系统&#xff0c;大模型正逐渐成为AI领域的新宠。在这个背景下&#xff0c;大模型的秋招&a…

ubuntu串口重命名助手x86_64电脑架构(秒速配好串口)(上)软件介绍

✨✨ Rqtz 个人主页 : 点击✨✨ &#x1f388;PyQt系列专栏:点击&#x1f388; &#x1f388;Qt智能车上位机专栏: 点击&#x1f388; &#x1f388;Qt串口助手专栏:点击&#x1f388; &#x1f4ab;宗旨:共享IT之美,共创机器未来 目录 ​编辑 ​编辑 项目背景 相关参数…

基于Pytorch框架的深度学习densenet121神经网络鸟类行为识别分类系统源码

第一步&#xff1a;准备数据 5种鸟类行为数据&#xff1a;self.class_indict ["bowing_status", "grooming", "headdown", "vigilance_status", "walking"] &#xff0c;总共有23790张图片&#xff0c;每个文件夹单独放一…

从零开始学习网络安全渗透测试之基础入门篇——(三)APP架构小程序H5+Vue语言Web封装原生开发Flutter

从零开始学习网络安全渗透测试之基础入门篇——&#xff08;三&#xff09; #APP架构&小程序&H5Vue语言&Web封装&原生开发&Flutter 确保App和小程序的安全性是移动应用开发中的重要环节。比如&#xff0c;代码混淆、数据加密、安全审计、权限管理、API安…

[240727] Qt Creator 14 发布 | AMD 推迟 Ryzen 9000芯片发布

目录 Qt Creator 14 发布Qt Creator 14 版本发布&#xff0c;带来一系列新功能和改进终端用户可通过命令行方式查看此新闻终端用户可通过命令行方式安装软件&#xff1a; AMD 推迟 Ryzen 9000芯片发布 Qt Creator 14 发布 Qt Creator 14 版本发布&#xff0c;带来一系列新功能…

IntelliJ IDEA 中安装 Groovy 插件 添加 Groovy SDK

一、在 IntelliJ IDEA 中安装 Groovy 插件可以按照以下步骤进行&#xff1a; 打开 IntelliJ IDEA&#xff1a; 启动 IntelliJ IDEA。 打开插件市场&#xff1a; 进入 File -> Settings&#xff08;在 macOS 上是 IntelliJ IDEA -> Preferences&#xff09;。在左侧菜单中…

信号、电源、网线、传感器防雷,SPD系列防雷器全覆盖!

信号、电源、网线、传感器防雷&#xff0c;SPD系列防雷器全覆盖&#xff01; SPD 系列防雷器是一种安装于被保护设备一侧的产品&#xff0c;旨在保护电子设备免受雷击、电磁脉冲、过压过渡冲击等造成的设备损坏。该产品广泛应用于工业控制、安全监测、网络通讯、交通电压等行业…

高速板开源工程的学习(一)

泰山派NAS-原理图和PCB设计经验分享-塞塞哇 (saisaiwa.com) BGA扇出的时候千万小心&#xff0c;导线到焊盘的距离大于0.1MM,千万小心&#xff0c;不然会寄寄的&#xff0c;这个在设计规则里面可以设置&#xff1a; 这种就容易造成阻焊开窗的误判&#xff0c;是很不规范的&…

力扣第三十七题——解数独

内容介绍 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 数独…