【数据结构】链式结构实现:二叉树

news2024/11/17 15:37:11

二叉树

  • 一.快速创建一颗二叉树
  • 二.二叉树的遍历
    • 1.前序、中序、后序遍历(深度优先遍历DFS)
    • 2.层序遍历(广度优先遍历BFS)
  • 三.二叉树节点的个数
  • 四.二叉树叶子节点的个数
  • 五.二叉树的高度
  • 六.二叉树第k层节点个数
  • 七.二叉树查找值为x的节点
  • 八.判断二叉树是否是完全二叉树
  • 九.二叉树的递归创建
  • 十.二叉树的销毁
  • 十一.二叉树必做OJ题
  • 十二.了解高级树

一.快速创建一颗二叉树

  1. 回顾⼆叉树的概念,⼆叉树分为空树和非空⼆叉树,非空⼆叉树由根结点、根结点的左子树、根结点的右子树组成的

  2. 根结点的左子树和右子树分别又是由子树结点、子树结点的左子树、子树结点的右子树组成的,因此⼆叉树定义是递归式的,后序链式⼆叉树的操作中基本都是按照该概念实现的。
    在这里插入图片描述

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("malloc fail!");
		return;
	}
	node->data = x;
	node->left = node->right = NULL;

	return node;
}

BTNode* CreatBinaryTree()
{
	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;
}

int main()
{
	BTNode* root = CreatBinaryTree();

	return 0;
}

二.二叉树的遍历

1.前序、中序、后序遍历(深度优先遍历DFS)

按照规则,⼆叉树的遍历有:前序/中序/后序的递归结构遍历:

  1. 前序遍历:访问根结点的操作发生在遍历其左右子树之前;访问顺序为:根结点、左子树、右子树

  2. 中序遍历:访问根结点的操作发生在遍历其左右子树中间;访问顺序为:左子树、根结点、右子树

  3. 后序遍历:访问根结点的操作发生在遍历其左右子树之后;访问顺序为:左子树、右子树、根结点

参考如下:

在这里插入图片描述
代码如下:

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

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

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

int main()
{
	BTNode* root = CreatBinaryTree();

	PrevOrder(root);
	printf("\n");

	InOrder(root);
	printf("\n");

	PosOrder(root);
	printf("\n");

	return 0;
}

在这里插入图片描述

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

在这里插入图片描述

注意:已知二叉树的前序和中序后序和中序就可以推导出二叉树的形状,但是只知道前序和后序则无法推导出二叉树的形状。

在这里插入图片描述

2.层序遍历(广度优先遍历BFS)

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

在这里插入图片描述

实现层序遍历需要用到队列,拷贝Queue.h与Queue.c文件到本地。

void TreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);

	if(root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		printf("%d ", front->val);

		// NULL无需入队列
		if(front->left)
			QueuePush(&q, front->left);
		if (front->right)
		QueuePush(&q, front->right);
	}

	QueueDestory(&q);
}

三.二叉树节点的个数

错误写法:

在这里插入图片描述

改进方法:

在这里插入图片描述

在这里插入图片描述

最好的方法:分治法(大问题化为多个小问题、小问题再化为多个小问题…直到不能再分为止)

  1. 空:0个
  2. 非空:左子树+右子树+1
int TreeSize(BTNode* root)
{
	if (root == NULL)
		return 0;

	return TreeSize(root->left) + TreeSize(root->right) + 1;
}

四.二叉树叶子节点的个数

  1. 空:0个
  2. 非空:若左子树和右子树同时为空返回1,否则左子树叶子节点+右子树叶子节点
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;

	if (root->left == NULL && root->right == NULL)
		return 1;

	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

五.二叉树的高度

  1. 空:0个
  2. 非空:MAX {左子树高度,右子树高度} + 1
//未记录高度导致重复大量的递归效率极低
//int TreeHeight1(BTNode* root)
//{
//	if (root == NULL)
//		return 0;
//
//	return TreeHeight(root->left) > TreeHeight(root->right) ?
//		TreeHeight(root->left) + 1 : TreeHeight(root->right) + 1;
//}

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

	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->left);

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

六.二叉树第k层节点个数

  1. 空:0个
  2. 非空且k==1:返回1
  3. 非空且k>1:左子树的k-1层节点个数+右子树的k-1层节点个数
int TreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;

	if (k == 1)
		return 1;

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

七.二叉树查找值为x的节点

  1. 空:返回NULL
  2. 非空且data==x:返回root
  3. 非空且data!=x:递归左子树+递归右子树,注意:要保存递归的结果层层返回
BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	BTNode* ret1 = TreeFind(root->left, x);
	if (ret1)
		return ret1;

	BTNode* ret2 = TreeFind(root->right, x);
	if (ret2)
		return ret2;

	return NULL;
}

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

注意:满二叉树可以利用树的高度,和节点的个数判断,但是完全二叉树前k-1层是满二叉树,最后一层不是满的,该方法就不行了。

可以利用层序遍历解决,方法如下:

在这里插入图片描述

bool TreeComplete(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)
		{
			QueueDestory(&q);
			return false;
		}	
	}

	//队列中没有非空节点,就是完全二叉树
	QueueDestory(&q);
	return true;
}

九.二叉树的递归创建

题目:已知前序遍历结果:abc##de#g##f###(其中#是NULL)
输出:中序遍历的结果(不包含NULL)

在这里插入图片描述

#include <stdio.h>
#include<stdlib.h>

typedef struct BinaryTreeNode
{
    char val;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;

BTNode* CreateTree(char* a, int* pi)
{
    //遇到#返回NULL
    if(a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }

    //创建根节点
    BTNode* root = (BTNode*)malloc(sizeof(BTNode));
    root->val = a[(*pi)++];

    //递归构建左子树
    root->left = CreateTree(a, pi);
    //递归构建右子树
    root->right = CreateTree(a, pi);

    //返回根节点
    return root;
}

void InOrder(BTNode* root)
{
    if(root == NULL)
        return;

    InOrder(root->left);
    printf("%c ", root->val);
    InOrder(root->right);
}

int main() {
    char a[100];
    scanf("%s", a);

    int i = 0;
    BTNode* root = CreateTree(a, &i); //注意:要传入地址

    InOrder(root);
}

十.二叉树的销毁

  1. 空:返回NULL
  2. 非空:后序遍历销毁节点
void TreeDestory(BTNode* root)
{
	if (root == NULL)
		return;

	TreeDestory(root->left);
	TreeDestory(root->right);
	free(root);
}

十一.二叉树必做OJ题

  1. 单值二叉树
  2. 相同的树
  3. 对称二叉树
  4. 二叉树的前序遍历
  5. 二叉树的中序遍历
  6. 二叉树的后序遍历
  7. 另一棵树的子树
  8. 二叉树遍历

十二.了解高级树

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

C++ //练习 17.23 编写查找邮政编码的正则表达式。一个美国邮政编码可以由五位或九位数字组成。前五位数字和后四位数字之间可以用一个短横线分隔。

C Primer&#xff08;第5版&#xff09; 练习 17.23 练习 17.23 编写查找邮政编码的正则表达式。一个美国邮政编码可以由五位或九位数字组成。前五位数字和后四位数字之间可以用一个短横线分隔。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#x…

【CTF | WEB】004、攻防世界WEB题目之simple_js

文章目录 simple_js题目描述:题目场景&#xff1a;解题思路 simple_js 题目描述: 小宁发现了一个网页&#xff0c;但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} ) 题目场景&#xff1a; 解题思路 尝试了一下随便输入密码&#xff0c;显示如下&#xff1a; 按下F1…

【高阶数据结构】图

图 1. 图的基本概念2. 图的存储结构2.1 邻接矩阵2.2 邻接表2.3 邻接矩阵的实现2.4 邻接表的实现 3. 图的遍历3.1 图的广度优先遍历3.2 图的深度优先遍历 4. 最小生成树4.1 Kruskal算法4.2 Prim算法 5. 最短路径5.1 单源最短路径--Dijkstra算法5.2 单源最短路径--Bellman-Ford算…

CVE-2024-34982 LyLme Spage六零导航页 任意文件上传漏洞漏洞分析

代码分析 文件位于/lylme_spage/include/file.php。 这是用于图片文件处理的 <?php /** Description: 图片文件处理* FilePath: /lylme_spage/include/file.php* Copyright (c) 2024 by LyLme, All Rights Reserved.*/ header(Content-Type:application/json); require_o…

【Linux基础】Linux中的开发工具(3)--make/makefile和git的使用

目录 前言一&#xff0c;Linux项目自动化构建工具-make/makefile1. 背景2. 依赖关系和依赖方法3. 项目清理4. 使用方法和原理5. .PHONY的作用6. makefile中符号的使用 二&#xff0c;进度条的实现1. 理解回车换行2. 理解行缓冲区3. 版本14. 版本2 三&#xff0c;Linux上git的使…

文件包含漏洞(一)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 一&#xff0c;漏洞简述。 文件包含漏洞&#xff0c;通常发生在Web应用程序中&#xff0c;特别是那些使用用户输入动态生成内容的部分。这种漏洞允许攻击者通过提交恶意的文件路径请…

AI预测福彩3D采取888=3策略+和值012路或胆码测试8月19日新模型预测第61弹

经过60期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;60期一共只错了6次&#xff0c;这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0c;大部…

【Neo4j系列】简化Neo4j数据库操作:一个基础工具类的开发之旅

作者&#xff1a;后端小肥肠 在Neo4j系列我打算写一个Neo4j同步关系数据库、增删改查及展示的基础小系统&#xff0c;这篇文件先分享系统里面的基础工具类&#xff0c;感兴趣的可以点个关注&#xff0c;看了文章的jym有更好的方法可以分享在评论区。 创作不易&#xff0c;未经允…

《勇敢的哈克》开发商:为Xbox移植游戏是一场噩梦

国产类银河恶魔城游戏《勇敢的哈克》开发商Blingame在尝试将游戏移植到Xbox上时&#xff0c;遭遇让人头痛的技术障碍&#xff0c;最终他们只能放弃。《勇敢的哈克》是一款融合了类银河恶魔城元素的末日废土风平台动作游戏。你需要利用多功能能量钩爪组合出独特技能&#xff0c;…

Jenkins使用Publish Over SSH插件远程部署程序到阿里云服务器

前言 使用Jenkins远程构建springboot服务到阿里云上&#xff0c;Jenkins版本&#xff1a;Version 2.462.1 1、准备 在可选插件中&#xff0c;搜索Maven Integration &#xff0c;Gitlab和 Publish Over SSH 三个插件&#xff1a; 如果需要多用户管理那就安装&#xff1a;Ro…

【MySQL进阶之路】表结构的操作

目录 创建表 查看表 查看数据库有哪些表 查看表结构 查看表的详细信息 修改表 表的重命名 添加一列 修改某一列的属性 删除某一列 对列进行重命名 删除表 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 【MySQL进阶之路】MySQL基础——从零认识MySQL-CSDN博客 创…

LLM技术揭秘:Qwen的Function Calling实现解析

简介 Function Calling 是一种让 Chat Completion 模型调用外部函数的能力&#xff0c;可以让模型不仅仅根据自身的数据库知识进行回答&#xff0c;而是可以额外挂载一个函数库&#xff0c;然后根据用户提问去函数库检索&#xff0c;按照实际需求调用外部函数并获取函数运行结…

授权cleanmymac访问全部磁盘 Mac授权访问权限 cleanmymac缺少权限

CleanMyMac是Mac系统下的一款专业的苹果电脑清理软件&#xff0c;同时也是一款优秀的电脑系统管理软件。它能有效清理系统垃圾&#xff0c;快速释放磁盘内存&#xff0c;缓解卡顿现象&#xff0c;保障系统顺畅地运行。 全磁盘访问权限&#xff0c;就好比机场内进行的安全检查。…

Vue3页面组件化开发

本节讲解Vue3页面组件化开发的原因和操作 1.原因 1.业务需求 2.页面展示 根据菜单选项展示不同的页面布局和页面信息 3.页面源码 <template><div class"box"><div class"UserInfo"><div class"UserImg"><img src&…

云计算第三阶段---DBA数据库管理

Day1 一.数据库概述 计算机中数据存放的仓库&#xff0c;可以按数据类型划分数据库&#xff0c;又可以在数据库中划分更细节的分类存放到相应的表中。 抽象来说就是生活中的菜市场、五金店之类的场所&#xff0c;根据用途开设&#xff1b;划分广泛的还有百货商场、批发市场等…

HarmonyOS应用程序访问控制探究

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 一、引言 随着信息技术的飞速发展&#xff0c;移动应用程序已经成为…

【C++】实现日期类相关接口

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇 本篇将介绍实现日期类中众多接口&#xff0c;同时这其中涉及到很多知识&#xff0c;务必将类和对象相关内容掌握再来实现日期类…

【数据结构】详细介绍栈和队列,解析栈和队列每一处细节

目录 一. 栈 1. 栈的概念 2. 栈的实现 2.1 栈的结构 2.2 初始化栈 2.3 入栈 2.4 出栈 2.5 获取栈顶元素 2.6 获取栈中有效个数 2.7 判断栈是否为空 2.8 销毁栈 二. 队列 1. 队列的概念 2. 队列的实现 2.1 队列的结构 2.2 队列初始化 2.3 销毁队列 2.4 入…

聊聊适配器模式

目录 适配器模式概念 主要实现方式 主要组成 UML用例图 代码示例 生活场景 应用场景 适配器模式概念 适配器模式属于结构型设计模式&#xff0c;它的主要目的是将一个类的接口转换成客户端所期望的另一种接口形式&#xff0c;使得原本接口不兼容的类可以一起工作。 主…

【New SQL】 -- CockroachDB license change

1、CockroachDB 发布了修改开源协议的 releases 北京时间 2024-08-16 &#xff0c;CockroachDB 发布了修改开源协议的 releases。 原文链接&#xff1a;Licensing FAQs Evolving our self-hosted offering and license model CockroachDB License change (again) | Product T…