二叉树的基本运算(涉及递归均有给出模型)

目录

介绍:

二叉树的基本运算及其实现:

BTNode* CreateBTree(char* str) 创建二叉树

void DestroyBTree(BTNode* b) 销毁二叉树

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

int BTHeight(BTNode* b) 求二叉树b的高度

最后总代码:

结语:


介绍:

二叉树的定义:二叉树由一个根结点和两棵互不相交的称为左子树(left subtree)和右子树(right subtree)的二叉树组成。

二叉树的存储结构:

(1)循序存储:(因其在极端条件下空间浪费极大故大部分二叉树都采用链式存储结构)

(2)链式存储

typedef struct node
{
    ElemType data;       //数据元素
    struct node* lchild;    //指向左孩子结点
    struct node* rchild;    //指向右孩子结点
}BTNode;     //二叉树的结构体

二叉树的基本运算及其实现:

特别说明下面运算均采用二叉链存储结构进行存储。

BTNode* CreateBTree(char* str) 创建二叉树

void DestroyBTree(BTNode* b) 销毁二叉树

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

int BTHeight(BTNode* b) 求二叉树b的高度

void DispBTree(BTNode* b) 以括号表示法输出二叉树

既然使用二叉链来进行实现的,那么必然就离不开链表,提到链表就不得不想到结构体。那么我们二叉树的结构体就来啦👀

说明:为了使描述简单故基本类型采用char类型,如果大家想修改的话把上面的char改成其它即可。

#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;
	struct node* lchild;
	struct node* rchild;
}BTNode;

BTNode* CreateBTree(char* str) 创建二叉树

采用括号表达式法表示二叉树,用ch遍历str,因为使括号表达式所以其中只有四类字符,例如下图:

其处理方式如下。

1:若ch=‘(’,表示前面的结点p存在孩子结点需要将其进栈(括号表达式一般都是要用到栈的)。

2:若ch=‘)’,表示以栈顶结点为根节点的子树创建完毕,将其退栈。

3:若ch=‘,’,表示要处理栈顶结点的有孩子结点,故置k=2

4:其它情况:只能是单个字符,对应二叉树中的某个结点值,需要创建一个结点p来存储该结点值。根据k值建立它与栈顶结点之间的联系。当k=1时,将结点p作为栈顶结点的左孩子;当k=2时,将结点p作为栈顶结点的右孩子。

用一个while把str数组全部遍历采用上面四条处理方法,我们的二叉树就创建好啦👌!!!

代码如下:

BTNode* CreateBTree(char* str)
{
	BTNode* b;
	BTNode* St[MaxSize];
	BTNode* p=NULL;
	int top = -1, k, j = 0;
	char ch;
	b = NULL;
	ch = str[j];
	while (ch != '\0') 
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break;
		case ')': top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
				b = p;
			else
			{
				switch (k)
				{
				case 1:St[top]->lchild = p; break;
				case 2:St[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}

void DestroyBTree(BTNode* b) 销毁二叉树

创建讲完,那么销毁必然少不了,想亲兄弟一样(形象吧(❁´◡`❁))


处理方式如下:二叉树最经常用到的莫过于递归了,没错我们的销毁就是用递归来完成的。

递归那么最重要的一定是思路,建议大家遇到递归的时候一定要在草稿纸上列出递归的模型,尤其是递归的出口一定要设置好!!!(下面我给出我的递归模型大家可以参考参考)

当b为NULL时什么也不做,当b不等于NULL时先释放左孩子子树的空间,再释放右孩子子树的空间,最后再释放b树的空间,为什么要按照这个循序呢?这是因为如果先释放了b那么我们的左右孩子子树就找不到了,那么内存就会泄露。(这个递归其实总的就执行free(b))

代码如下:

void DestroyBTree(BTNode* b)
{
	if (b != NULL)
	{
		DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
	return;
}

BTNode* FindNode(BTNode* b, ElemType x) 查找结点

其功能是在二叉树b中查找值为x的结点,找到后返回其地址,否则返回NULL。

处理方式如下:没错这里的实现又是递归。对于递归的解释在上面的销毁哪我已经讲的很清楚了,故这里不在过多赘述。递归的模型如下:

对着上面的这张图,那么代码实现就非常简单啦🤳🤳🤳

代码如下:

BTNode* FindNode(BTNode* b, ElemType x)
{
	BTNode* p;
	if (b == NULL) return NULL;
	else if (b->data == x) return b;
	else
	{
		p = FindNode(b->lchild, x);
		if (p != NULL) return p;
		else return FindNode(b->rchild,x);
	}
}

BTNode* LchildNode(BTNode* p) 查找左孩子结点

BTNode* RchildNode(BTNode* p) 查找右孩子结点

由于这两个基本算法的实现和功能基本一致故这里我们两个一起来(因为简单故直接上代码)

代码如下:

BTNode* LchildNode(BTNode* p)
{
	return p->lchild;
}
BTNode* RchildNode(BTNode* p)
{
	return p->rchild;
}

int BTHeight(BTNode* b) 求二叉树b的高度

有树那么就有高度,高的树价值大,高的二叉树占的空间大。

处理方法:递归实现,递归的模型如下:

依图代码实现如下:

特别注意:规定空树的高度为0,只有一个根高度为1

int BTHeight(BTNode* b)
{
	int lchildh, rchildh;
	if (b == NULL) return 0;
	else
	{
		lchildh = BTHeight(b->lchild);
		rchildh = BTHeight(b->rchild);
		return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
	}
}

void DispBTree(BTNode* b) 以括号表示法输出二叉树

最后就是输出二叉树了,实现方法:递归,有孩子结点时才输出‘(’,递归输出左子树,有右孩子结点才输出‘,’,递归输出右子树,有孩子结点时才输出‘)’。具体递归模型如下:

因为存储时,我们并没有存储括号和逗号,故在输出时,我们要人为的给它们加上。

具体代码实现如下:

void DispBTree(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c", b->data);
		if (b->lchild != NULL || b->rchild != NULL)
		{
			printf("(");
			DispBTree(b->lchild);
			if (b->rchild != NULL) printf(",");
			DispBTree(b->rchild);
			printf(")");
		}
	}
}

最后总代码:

有给出括号表达式供大家进行代码调试并理解代码。

#define  _CRT_SECURE_NO_WARNINGS 1
//二叉树的基本运算
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;
	struct node* lchild;
	struct node* rchild;
}BTNode;
BTNode* CreateBTree(char* str)
{
	BTNode* b;
	BTNode* St[MaxSize];
	BTNode* p=NULL;
	int top = -1, k, j = 0;
	char ch;
	b = NULL;
	ch = str[j];
	while (ch != '\0') 
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break;
		case ')': top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
				b = p;
			else
			{
				switch (k)
				{
				case 1:St[top]->lchild = p; break;
				case 2:St[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}
void DestroyBTree(BTNode* b)
{
	if (b != NULL)
	{
		DestroyBTree(b->lchild);
		DestroyBTree(b->rchild);
		free(b);
	}
	return;
}
BTNode* FindNode(BTNode* b, ElemType x)
{
	BTNode* p;
	if (b == NULL) return NULL;
	else if (b->data == x) return b;
	else
	{
		p = FindNode(b->lchild, x);
		if (p != NULL) return p;
		else return FindNode(b->rchild,x);
	}
}
BTNode* LchildNode(BTNode* p)
{
	return p->lchild;
}
BTNode* RchildNode(BTNode* p)
{
	return p->rchild;
}
int BTHeight(BTNode* b)
{
	int lchildh, rchildh;
	if (b == NULL) return 0;
	else
	{
		lchildh = BTHeight(b->lchild);
		rchildh = BTHeight(b->rchild);
		return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
	}
}
void DispBTree(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c", b->data);
		if (b->lchild != NULL || b->rchild != NULL)
		{
			printf("(");
			DispBTree(b->lchild);
			if (b->rchild != NULL) printf(",");
			DispBTree(b->rchild);
			printf(")");
		}
	}
}
int main()
{
	char str[] = "A(B(D(,G)),C(E,F))";
	BTNode* b = CreateBTree(str);
	DispBTree(b);
	return 0;
}

以上便是二叉树的基本运算,那么我们的文章就好这里结束啦🎉🎉🎉

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自学Python笔记总结(更新中……)

自学Python笔记总结 网址数据类型类型查看类型&#xff0c;使用type内置类标识符 输出输入语句format函数的语法及用法数据类型的转换运算符算数运算符赋值运算符的特殊场景拆包 比较运算符逻辑运算符 与 短路位运算符运算符优先级 程序流程控制分支语句pass 占位 循环语句 whi…

【记忆化搜索】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 前言 记忆化搜索是一种优化搜索算法的方法&#xff0c;它可…

网络基础学习(3):交换机

1.交换机结构 &#xff08;1&#xff09;网线接口和后面的电路部分加在一起称为一个端口&#xff0c;也就是说交换机的一个端口就相当于计算机上的一块网卡。 如果在计算机上安装多个网卡&#xff0c;并让网卡接收所有网络包&#xff0c;再安装具备交换机功能的软件&#xff0…

NLP论文阅读记录 - 2022 | WOS 数据驱动的英文文本摘要抽取模型的构建与应用

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结 前言 Construction and Application of a Data-Driven Abstract Extractio…

社会科学杂志社会科学杂志社社会科学编辑部2023年第12期部分目录

铁路部门档案管理中存在的问题及对策 尚芝维 公共图书馆共享服务模式分析 高翔 关于加强国有企业固定资产管理的对策 任美琪 大数据时代高校档案管理人才队伍建设策略 胡永芳 数据治理背景下档案数据馆员能力建设研究 许颖 新时代事业单位档案管理人才培养…

做品牌,怎么挖掘用户深层需求?

品牌想要长久发展&#xff0c;就需要去挖掘用户深层需求&#xff0c;什么是用户深层需求&#xff0c;比如做美业的认为用户想要变美是深层次的需求&#xff0c;但其实由美貌带来的附加利益比如说更上镜、竞争优势更大等才属于深层需求&#xff0c;今天媒介盒子就来和大家聊聊&a…

基于树莓派5(Raspberry Pi 5)的高性能工业平板电脑升级版!

​ 上海晶珩继推出首个搭载 Raspberry Pi 5 的平板电脑ED-HMI3010系列后&#xff0c;又推出了具备高性能和多功能特性的 Raspberry Pi 5 的平板电脑ED-HMI3020系列。ED-HMI3020支持选择7英寸和10.1英寸两种尺寸的触摸屏&#xff0c;可选配 M.2 NVMe SSD 存储扩展&#xff0c;提…

ros rqt_bag 用法汇总和用例

文章目录 基本用法高级功能典型用例 rqt_bag 是一个用于ROS&#xff08;机器人操作系统&#xff09;中查看和编辑bag文件的工具。Bag文件是ROS用于记录和回放消息数据的一种格式。以下是 rqt_bag 的主要用法汇总和一些典型用例&#xff1a; 基本用法 启动 rqt_bag 在终端中输入…

FineBI实战项目一(19):每小时订单笔数分析开发

点击新建组件&#xff0c;创建下每小时订单笔数组件。 选择饼图&#xff0c;拖拽cnt&#xff08;总数&#xff09;到角度&#xff0c;拖拽hourstr到颜色&#xff0c;调节内径。 修改现在的文字 拖拽组件到仪表盘。 效果如下&#xff1a;

如何在 PHP 中动态调用类中的方法?

在PHP中&#xff0c;我们可以通过动态调用类方法的方式来实现更加灵活的编程。这种方法可以使我们在运行时根据具体的需要来动态调用类中的方法。 1.使用call_user_func函数 PHP中提供了call_user_func函数用于动态调用类方法。 call_user_func(array($object, $methodName), $…

网络机顶盒什么牌子好?横评30款整理网络机顶盒排行榜

网络机顶盒什么牌子好是大家热议话题&#xff0c;每次发布完测评后会有网友评论不知道如何挑选网络机顶盒&#xff0c;希望我能分享网络机顶盒排行榜&#xff0c;为此我自费购入三十款网络机顶盒&#xff0c;通过多角度对比后整理了这份网络机顶盒排行榜&#xff0c;想知道网络…

element + table 每两行对比相同值列合并

在开始之前先要明确几个概念&#xff1a; 保持不变&#xff1a;{ rowspan: 1, colspan: 1 } 删除一个单元格&#xff1a;{ rowspan: 0, colspan: 0 } 合并一个单元格&#xff1a;{ rowspan: 2, colspan: 1 } <template><div><el-table:data"tableData&quo…

1.15寒假集训

A: 解题思路&#xff1a; 题目意思就是找大于等于n的最小3的倍数&#xff0c;当&#xff4e;为&#xff13;的倍数时&#xff0c;最小就为&#xff4e;&#xff0c;否则输出&#xff13; * (n / 3 1)。 下面是c代码&#xff1a; #include<iostream> using namespace…

Java中单体应用锁的局限性分布式锁

互联网系统架构的演进 在互联网系统发展之初&#xff0c;系统比较简单&#xff0c;消耗资源小&#xff0c;用户访问量也比较少&#xff0c;我们只部署一个Tomcat应用就可以满足需求。系统架构图如下: 一个Tomcat可以看作是一个JVM进程&#xff0c;当大量的请求并发到达系统时&…

聚合收益协议 InsFi :打开铭文赛道全新叙事的旋转门

​“InsFi 协议构建了一套以铭文资产为基础的聚合收益体系&#xff0c;该体系正在为铭文资产捕获流动性、释放价值提供基础&#xff0c;该生态也正在成为铭文赛道掘金的新热土。” 在 2023 年年初&#xff0c;Ordinals 协议在比特币链上被推出后&#xff0c;为比特币链上带来了…

点击切换图片,样式

切换场景&#xff1a; 本文章向大家介绍uniapp之 点击图片切换&#xff0c;使用实例、应用技巧、基本知识点总结和需要注意事项&#xff0c;具有一定的参考价值&#xff0c;需要的朋友可以参考一下。 提示&#xff1a;点击时进行角色切换&#xff0c;【图片切换&#xff0c;并…

idea安装go

1.根据系统平台&#xff0c;下载安装Go&#xff1a; 知乎 - 安全中心 2.windows系统&#xff0c;下载安装MinGW(gcc)&#xff1a; 知乎 - 安全中心 3.安装后cmd输入一下 go env 4.代理设置 go env -w GOPROXYhttps://goproxy.cn,direct 5.idea插件安装 file->setti…

Pandas.DataFrame.loc[ ] 筛选数据-标签法 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.1.2 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 Pandas稳定版更新及变动内容整合专题&#xff1a; Pandas稳定版更新及变动迭持续更新。 Pandas API参…

Win和Mac系统重置系统方法

注意&#xff1a;重置系统前&#xff0c;请备份好系统盘资料到其他盘符&#xff01;重置系统将会删除应用和系统设置&#xff0c;甚至用户文件&#xff0c;还原为出厂设置模式。 Windows重置系统操作方法。&#xff08;目前支持WIN8&#xff0c;WIN10&#xff0c;WIN11&#x…

Hotspot源码解析-第十九章-ClassLoaderData、符号表、字符串表的初始化

第十九章-ClassLoaderData初始化 讲解本章先从一张图开始 众所周知&#xff0c;Java类的相关信息都是存储在元空间中的&#xff0c;但是是怎么存储的&#xff0c;相信很多读者是不清楚的&#xff0c;这里就不得不涉及到ClassLoaderDataGraph、classLoader、classLoaderData&…