草庐IT

二叉树相关操作---纯代码实现详解

小张﹉ 2023-07-19 原文

目录

前言 (很重要)

二叉树的概念

二叉树的相关术语

相关操作菜单

  二叉树的构造

 创建二叉树

先序遍历二叉树  

 中序遍历二叉树

 后序遍历二叉树

 层次遍历二叉树

 二叉树的深度

 二叉树的叶子结点数

 二叉树的结点数

整体代码

结果展示

结束语


前言 (很重要)

        大家好,今天给大家带来的是二叉树的相关操作,希望能够给大家带来帮助。

        另外有很多小伙伴们在学习算法的时候,只去学习一些关于算法理论的知识,并不知道自己的代码实战能力如何也不清楚到底对该算法的了解有多深,所以在这里小张给大家推荐一个很棒的平台,在这里有很多的面试和算法题,也有很多的面试和求职的机会,大家可以点击下方链接进入牛客网刷算法真题,提高自己代码实战能力,早日拿到满意的offer!点击这里进入牛客网刷算法和面试真题提高代码实战能力

二叉树的概念

        二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 。

二叉树的相关术语

①节点:包含一个数据元素及若干指向子树分支的信息 。

②节点的度:一个节点拥有子树的数目称为节点的度 。

③叶子节点:也称为终端节点,没有子树的节点或者度为零的节点 。

④分支节点:也称为非终端节点,度不为零的节点称为非终端节点 。

⑤树的度:树中所有节点的度的最大值 。

⑥节点的层次:从根节点开始,假设根节点为第1层,根节点的子节点为第2层,依此类推,如果某一个节点位于第L层,则其子节点位于第L+1层 。

⑦树的深度:也称为树的高度,树中所有节点的层次最大值称为树的深度  

相关操作菜单

//菜单
void menu()
{
	cout << "\t\t\t******************************************************************" << endl;
	cout << "\t\t\t****************  1.输入-1  退出程序           *******************" << endl;
	cout << "\t\t\t****************  2.输入1   初始化二叉树       *******************" << endl;
	cout << "\t\t\t****************  3.输入2   对二叉树先序遍历   *******************" << endl;
	cout << "\t\t\t****************  4.输入3   对二叉树中序遍历   *******************" << endl;
	cout << "\t\t\t****************  5.输入4   对二叉树后序遍历   *******************" << endl;
	cout << "\t\t\t****************  6.输入5   对二叉树层次遍历   *******************" << endl;
	cout << "\t\t\t****************  7.输入6   二叉树深度         *******************" << endl;
	cout << "\t\t\t****************  8.输入7   二叉树叶子结点数   *******************" << endl;
	cout << "\t\t\t****************  9.输入8   二叉树的结点数     *******************" << endl;
	cout << "\t\t\t******************************************************************" << endl;
}

  二叉树的构造

//构造二叉树
typedef struct Binode
{
	//数据域
	char data;
	//定义左孩子和右孩子
	struct Binode*lchid, *rchid;
}Binode, *StrBinode;

 创建二叉树

//先序遍历创建二叉树
void creatBinode(StrBinode&T)
{
	cin >> ch;
	if (ch == '#')
	{
		//如果输入是#的话就说明根结点就是叶子结点
		//就没必要再去进行开辟一个二叉树空间
		T = NULL;
	}
	else
	{
		T = new Binode;
		T->data = ch;
		creatBinode(T->lchid);
		creatBinode(T->rchid);
	}
}

先序遍历二叉树  

//先序遍历二叉树
void visitBinode(StrBinode&T)
{
	if (T!=NULL)
	{
		cout << T->data << " ";
		visitBinode(T->lchid);
		visitBinode(T->rchid);
	}
	if(T==NULL)
	{
		cout << "#" << " ";
	}
}

 中序遍历二叉树

//中序遍历二叉树
void MidvisitBinode(StrBinode&T)
{
	if (T != NULL)
	{
		visitBinode(T->lchid);
		cout << T->data << " ";
		visitBinode(T->rchid);
	}
	if (T == NULL)
	{
		cout << "#" << " ";
	}
}

 后序遍历二叉树

//后序遍历二叉树
void BackvisitBinode(StrBinode&T)
{
	if (T != NULL)
	{
		visitBinode(T->lchid);
		visitBinode(T->rchid);
		cout << T->data << " ";
	}
	if (T == NULL)
	{
		cout << "#" << " ";
	}
}

 层次遍历二叉树

//二叉树的层次遍历
void Levelorder(StrBinode&HT)
{
	StrBinode T;
	T = new Binode;
	//创建一个队列qu
	queue<StrBinode> qu;
	//将根结点的指针压入队列
	qu.push(HT);
	//当队列不为空的时候就继续进行循环
	while (!qu.empty())
	{
		//让T里面存放队列中第一个元素的值
		T = qu.front();
		//C++自带的队列出队的话是删除值不返回值
		qu.pop();
		//访问出队元素的值
		cout << T->data << " ";
		//当该节点左孩子不为空的时候就让左孩子入队
		if (T->lchid != NULL)
		{
			qu.push(T->lchid);
		}
		//当该节点右孩子不为空的时候就让左孩子入队
		if (T->rchid != NULL)
		{
			qu.push(T->rchid);
		}
	}
	
}

 二叉树的深度

//二叉树的深度
int deep(StrBinode&T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		int m = deep(T->lchid);
		int n = deep(T->rchid);
		if (m > n)
		{
			return (m + 1);
		}
		else
		{
			return (n + 1);
		}
	}
}

 二叉树的叶子结点数

//求二叉树的叶子结点
int leaf(StrBinode&T)
{
	//如果是空树
	if (T == NULL)
	{
		//返回0
		return 0;
	}
	//如果是叶子结点
	if (T->lchid == NULL && T->rchid == NULL)
	{
		//返回1
		return 1;
	}
	return leaf(T->lchid) + leaf(T->rchid);
}

 二叉树的结点数

//求二叉树的结点数
int Nodecount(StrBinode&T)
{
	//如果是根结点没有数据
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return Nodecount(T->lchid) + Nodecount(T->rchid) + 1;
	}
}

整体代码

#include<iostream>
#include<queue>
using namespace std;
char ch = 0;

//构造二叉树
typedef struct Binode
{
	//数据域
	char data;
	//定义左孩子和右孩子
	struct Binode*lchid, *rchid;
}Binode, *StrBinode;

//先序遍历创建二叉树
void creatBinode(StrBinode&T)
{
	cin >> ch;
	if (ch == '#')
	{
		//如果输入是#的话就说明根结点就是叶子结点
		//就没必要再去进行开辟一个二叉树空间
		T = NULL;
	}
	else
	{
		T = new Binode;
		T->data = ch;
		creatBinode(T->lchid);
		creatBinode(T->rchid);
	}
}

//先序遍历二叉树
void visitBinode(StrBinode&T)
{
	if (T!=NULL)
	{
		cout << T->data << " ";
		visitBinode(T->lchid);
		visitBinode(T->rchid);
	}
	if(T==NULL)
	{
		cout << "#" << " ";
	}
}

//中序遍历二叉树
void MidvisitBinode(StrBinode&T)
{
	if (T != NULL)
	{
		visitBinode(T->lchid);
		cout << T->data << " ";
		visitBinode(T->rchid);
	}
	if (T == NULL)
	{
		cout << "#" << " ";
	}
}

//后序遍历二叉树
void BackvisitBinode(StrBinode&T)
{
	if (T != NULL)
	{
		visitBinode(T->lchid);
		visitBinode(T->rchid);
		cout << T->data << " ";
	}
	if (T == NULL)
	{
		cout << "#" << " ";
	}
}

//二叉树的层次遍历
void Levelorder(StrBinode&HT)
{
	StrBinode T;
	T = new Binode;
	//创建一个队列qu
	queue<StrBinode> qu;
	//将根结点的指针压入队列
	qu.push(HT);
	//当队列不为空的时候就继续进行循环
	while (!qu.empty())
	{
		//让T里面存放队列中第一个元素的值
		T = qu.front();
		//C++自带的队列出队的话是删除值不返回值
		qu.pop();
		//访问出队元素的值
		cout << T->data << " ";
		//当该节点左孩子不为空的时候就让左孩子入队
		if (T->lchid != NULL)
		{
			qu.push(T->lchid);
		}
		//当该节点右孩子不为空的时候就让左孩子入队
		if (T->rchid != NULL)
		{
			qu.push(T->rchid);
		}
	}
	
}

//二叉树的深度
int deep(StrBinode&T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		int m = deep(T->lchid);
		int n = deep(T->rchid);
		if (m > n)
		{
			return (m + 1);
		}
		else
		{
			return (n + 1);
		}
	}
}

//求二叉树的叶子结点
int leaf(StrBinode&T)
{
	//如果是空树
	if (T == NULL)
	{
		//返回0
		return 0;
	}
	//如果是叶子结点
	if (T->lchid == NULL && T->rchid == NULL)
	{
		//返回1
		return 1;
	}
	return leaf(T->lchid) + leaf(T->rchid);
}

//求二叉树的结点数
int Nodecount(StrBinode&T)
{
	//如果是根结点没有数据
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return Nodecount(T->lchid) + Nodecount(T->rchid) + 1;
	}
}

//菜单
void menu()
{
	cout << "\t\t\t******************************************************************" << endl;
	cout << "\t\t\t****************  1.输入-1  退出程序           *******************" << endl;
	cout << "\t\t\t****************  2.输入1   初始化二叉树       *******************" << endl;
	cout << "\t\t\t****************  3.输入2   对二叉树先序遍历   *******************" << endl;
	cout << "\t\t\t****************  4.输入3   对二叉树中序遍历   *******************" << endl;
	cout << "\t\t\t****************  5.输入4   对二叉树后序遍历   *******************" << endl;
	cout << "\t\t\t****************  6.输入5   对二叉树层次遍历   *******************" << endl;
	cout << "\t\t\t****************  7.输入6   二叉树深度         *******************" << endl;
	cout << "\t\t\t****************  8.输入7   二叉树叶子结点数   *******************" << endl;
	cout << "\t\t\t****************  9.输入8   二叉树的结点数     *******************" << endl;
	cout << "\t\t\t******************************************************************" << endl;
}

int main()
{
	int n = 0;
	StrBinode T;
	menu();
	while (cin >> n)
	{
		if (n < 0)
		{
			break;
		}
		switch (n)
		{
		case 1:
			//初始化二叉树
			cout << "请输入值对二叉树进行初始化" << endl;
			creatBinode(T);
			cout << "初始化完成" << endl;
			break;
		case 2:
			//先序遍历
			cout << "先序遍历的结果为" << endl;
			visitBinode(T);
			cout << "先序遍历结束" << endl;
			break;
		case 3:
			//中序遍历
			cout << "中序遍历的结果为" << endl;
			MidvisitBinode(T);
			cout << "中序遍历结束" << endl;
			break;
		case 4:
			//后序遍历
			cout << "后序遍历的结果为" << endl;
			BackvisitBinode(T);
			cout << "后序遍历结束" << endl;
			break;
		case 5:
			//层次遍历
			cout << "层次遍历的结果为" << endl;
			Levelorder(T);
			cout << "层次遍历结束" << endl;
			break;
		case 6:
			cout << "二叉树的深度为:";
			cout << deep(T) << endl;
			break;
		case 7:
			cout << "二叉树的叶子结点数为:";
			cout << leaf(T) << endl;
			break;
		case 8:
			cout << "二叉树的结点数为;";
			cout << Nodecount(T) << endl;
			break;
		default:
			cout << "您的输入有误,请重新输入" << endl;
			break;
		}
	}
	return 0;
}

结果展示

结束语

        到这里今天的内容就已经全部结束了,这里的代码是运用C++语言实现的,其他语言的话也大同小异,只要相关的思想掌握了,就能写出来相应的代码最后小张在这里感谢大家的支持 !

有关二叉树相关操作---纯代码实现详解的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  8. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  9. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐