二叉树1:二叉树的基本运算

1. (简答题)

       编写一个程序,实现二叉树的基本运算,具体要求如下:(指定示范实例1:P243图7.34。指定示范实例2:P201图7.13 )

1,括号表示法输出该树。

2,输入一个结点的值,输出该结点的左,右孩子的值。(要能测试错误数据)

3,输出该二叉树的高度。

4,输出该二叉树结点的个数。

5,输出该二叉树双分支结点的个数。

6,输出该二叉树单分支结点的个数。

7,输出该二叉树叶子结点的个数。

8,输出该二叉树的宽度。(宽度为每层结点数的最大值)

9,(选做题)任意给定该二叉树的两个结点,输出它们的最近的公共祖先。(例:对P243图7.34,输入J, N,它们的祖先是H,E,B,A,最近的祖先是H。  另外一组测试数据为:L,E的公共祖先是:E。 )

10,销毁该二叉树。

//二叉树
#include<bits/stdc++.h>
using namespace std;
#define MAX 10000
#define MIN -1
typedef char ch;
int ans=MIN,w[100]={0};//假设这课树的高度不超100
//首先每个节点的属性如下有数据域,左右孩子
typedef struct BTnode
{
	ch data;
	struct BTnode *lchild;
	struct BTnode *rchild;
}BT;//注意这个是节点的定义
//解读树,用二叉链的形式
void CreatBtree(BT *&B1,ch *str)//输入我们创建的树和树的括号表示法
{//B1是我们的树,str是括号表示法的那串字符
	BT *st[MAX],*p;//B作为一个顺序栈。p就是我们扫描的元素
	int top=-1,k,j=0;ch l;//top是表示栈顶,k表示左右孩子,j是遍历a用的
	B1=NULL;
	l=str[j];
	while(l!='\0'){
		//总结一下:(入栈(表示这条分支的开始),)退栈(因为结束了),遇到元素就创建节点,
		//遇到逗号改k(左右孩子),见下面的注释一
		switch (l) {
		case '(':top++;st[top]=p;k=1;break;
		case ')':top--;break;
		case ',':k=2;break;
		default:
			p=new BT;
			p->data=l;
			p->lchild=p->rchild=NULL;
			if(B1==NULL)//头结点
				B1=p;
			else
			{
				switch (k) {
				case 1:st[top]->lchild=p;break;
				case 2:st[top]->rchild=p;break;
				}
			}
		}
		j++;
		l=str[j];
	}
}
//以值找p
BT *Findmyposition(BT *B1,ch str)
{
	BT *p;
	if(B1==NULL)//空树找不到
		return NULL;
	else if(B1->data==str)//根是的话就返回根
		return B1;
	else{//否则开始递归找(先搜索左)
		p=Findmyposition(B1->lchild,str);
		//p如果最后为空,说明没找到 ,那就找右节点
		//如果找到就不找了
		if(p!=NULL)
			return p;
		else
			return Findmyposition(B1->rchild,str);
	}
	
}
//寻找左右孩子
BT *Lchildnode(BT *p)//返回一个地址
{
	return p->lchild;//理解上面创建的过程就可以理解这个
}
BT *Rchildnode(BT *p)
{
	return p->rchild;
}
//高度
int BTheight(BT *B1)
{
	int l,r;
	if(B1==NULL)
		return 0;
	else
	{
		l=BTheight(B1->lchild);
		r=BTheight(B1->rchild);
		return ((l>r)?l+1:r+1);	
	}
}
//节点数
int BTcount(BT *B1)
{
	if(B1==NULL)
		return 0;
	else
		return BTcount(B1->lchild)+BTcount(B1->rchild)+1;
}
int BTdoublecount(BT *B1)
{
	if(B1==NULL)
		return 0;
	else if(B1->lchild!=NULL&&B1->rchild!=NULL)
		return BTdoublecount(B1->lchild)+BTdoublecount(B1->rchild)+1;
	else
		return BTdoublecount(B1->lchild)+BTdoublecount(B1->rchild);
}
int BTsinglecount(BT *B1)
{
	if(B1==NULL)
		return 0;
	else if((B1->lchild!=NULL&&B1->rchild!=NULL)||(B1->lchild==NULL&&B1->rchild==NULL))
		return BTsinglecount(B1->lchild)+BTsinglecount(B1->rchild);
	else
		return BTsinglecount(B1->lchild)+BTsinglecount(B1->rchild)+1;
}
int BTleavescount(BT *B1)
{
	if(B1==NULL)
		return 0;
	else if(B1->lchild==NULL&&B1->rchild==NULL)
		return BTleavescount(B1->lchild)+BTleavescount(B1->rchild)+1;
	else
		return BTleavescount(B1->lchild)+BTleavescount(B1->rchild);
}
//宽度计算
int BTwcount(BT *B1,int h)
{
	if(B1==NULL)
		return 0;
	w[h]++;
	ans=((w[h]>ans)?w[h]:ans);
	BTwcount(B1->lchild,h+1);
	BTwcount(B1->rchild,h+1);
	return ans;
}
bool Findallparent(BT *B1,ch str,stack<ch>&s1)
{
	if(B1==NULL)
		return false;
	s1.push(B1->data);
	if(B1->data==str)//为什么这样子,根据题目提示,本身也可以是祖先,所以我们把本身也压入.
		return true;//找到了就结束
	bool flag=Findallparent(B1->lchild,str,s1);//没搜索到本点就继续
	if(flag)
		return true;//如果在左支找到了,退出
	flag=Findallparent(B1->rchild,str,s1);//否则右支
	if(flag)
		return true;
	s1.pop();//没找到就回溯
	return false;
}
//寻找最近共同祖先
ch Findsameparent(BT *B1,ch str1,ch str2)
{
	stack<ch> s1,s2;
	Findallparent(B1,str1,s1);
	Findallparent(B1,str2,s2);
	int p1=s1.size(),p2=s2.size();
	if(p1>p2)//令两栈位于同一层
	{
		int n=p1-p2;
		while(n){
			s1.pop();
			n--;
		}
	}
	else
	{
		int n=p2-p1;
		while(n){
			s2.pop();
			n--;
		}
	}
	while(s1.top()!=s2.top())
	{
		s1.pop();s2.pop();
		if(s1.top()==s2.top())
			return s1.top();
	}
	if(s1.top()==s2.top())
		return s1.top();
	return 0;
}
//销毁
void DestroyBTree(BT *&B1)
{
	if(B1!=NULL)
	{//从根出发开始删除
		DestroyBTree(B1->lchild);
		DestroyBTree(B1->rchild);
		delete B1;
	}
}
int main()
{
	int n;BT *B1;
	B1=new BT;ch a[MAX];
	cout<<"请选择您要测试的样例(输入1或2)";
	cin>>n;cout<<endl;
	if(n==1){
		cout<<"1.括号表示法表示这个树(样例一):A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I))"<<endl<<endl;
		strcpy(a, "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I))");
	}
	else if(n==2){
		cout<<"1.括号表示法表示这个树(样例二):A(B(D(,G),),C(E,F))"<<endl<<endl;
		strcpy(a, "A(B(D(,G),),C(E,F))");
	}
	else
	{
		cout<<"WARNING:what are you doing?"<<endl<<endl<<"输入1或2,ok?"<<endl<<endl;//防伪标识
		return 1;
	}
	CreatBtree(B1,a);
	//输入一个节点值,输出左右孩子
	cout<<"2.请您输入您要查询的节点的值:";
	ch o;cin>>o;cout<<endl;
	BT *p=Findmyposition(B1,o);
	if(p==NULL)
		cout<<"您的输入错误,该树无此结点!"<<endl<<endl;
	else{ 
	BT *k=Lchildnode(p);
	if(!k)
		cout<<o<<"无左孩子!"<<endl<<endl;
	else
		cout<<o<<"的左孩子是:"<<k->data<<endl<<endl;
	k=Rchildnode(p);
	if(!k)
		cout<<o<<"无右孩子!"<<endl<<endl;
	else
		cout<<o<<"的右孩子是:"<<k->data<<endl<<endl;
	}
	//输出高度
	cout<<"3.该二叉树的高度为:"<<BTheight(B1)<<endl<<endl;
	cout<<"4.该二叉树的节点个数为:"<<BTcount(B1)<<endl<<endl;
	cout<<"5.该二叉树双分支结点的个数:"<<BTdoublecount(B1)<<endl<<endl;
	cout<<"6.该二叉树单分支结点的个数:"<<BTsinglecount(B1)<<endl<<endl;
	cout<<"7.该二叉树叶子结点的个数:"<<BTleavescount(B1)<<endl<<endl;
	cout<<"8.该二叉树的宽度:"<<BTwcount(B1,0)<<endl<<endl;
	cout<<"9.请输入二叉树的两个结点:";ch h,x;cin>>h>>x;cout<<endl;
	cout<<"它们的最近的公共祖先是:"<<Findsameparent(B1,h,x)<<endl<<endl;
	cout<<"是否继续?(0退出,1继续)";int y;cin>>y;cout<<endl;
	while(y){
		cout<<"9.请输入二叉树的两个结点:";cin>>h>>x;cout<<endl;
		cout<<"它们的最近的公共祖先是:"<<Findsameparent(B1,h,x)<<endl<<endl;
		cout<<"是否继续?(0退出,1继续)";cin>>y;cout<<endl;
		
	}
	//销毁二叉树
	DestroyBTree(B1);
	cout<<"10.销毁二叉树成功!!!"<<endl<<endl;
	return 0;
} 


//我的蒟蒻见解
//注释一:我对(的理解是递归中根的确立,先放到栈顶,在未遇到)之前他的左孩子就接到栈顶的
//左指针域,右孩子接到右指针域,如果是左孩子遇到了(那就左孩子入栈,继续这样子的步骤,直到遇到
//)表示结束最近的那个根的左右寻找,然后一步一步回去,类似dfs不完全像,我做了个图,可以参考一下!
//发现了一个技巧,字母后面的(直接看出这个字母进栈的标志)

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

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

相关文章

C语言例题34、反向输出字符串(递归方式)

题目要求&#xff1a;输入5个字符后&#xff0c;使用递归方式逆序输出 #include <stdio.h>void reverse(int num) {char cur_char;if (num 1) {cur_char getchar();printf("逆序输出为&#xff1a;");putchar(cur_char);} else {cur_char getchar();revers…

宏电全栈式IoT赋能供排水智能监测,护航城市生命线

城市供水、排水系统是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市的“生命线”。随着城市化进程加快&#xff0c;城市规模不断扩大&#xff0c;地下管线增长迅速&#xff0c;城市“生命线安全”的监管日益面临挑战。 宏电作为物联网行业的领航者…

软件测试与管理:黑盒测试-等价类划分法和 边界值分析法

知识思维导图&#xff1a; 例题1&#xff1a;日期检查功能的等价类划分 设有一个档案管理系统&#xff0c;要求用户输入以年月表示的日期。假设日期限定在1990年1月~2049年12月&#xff0c;并规定日期由6位数字字符组成&#xff0c;前4位表示年&#xff0c;后2位表示月。现用等…

后台启动HIVE的JDBC连接

后台启动HIVE的JDBC连接 生活就像一杯咖啡&#xff0c;有时苦涩&#xff0c;有时香甜&#xff0c;但都是值得品味的经历。无论遇到什么挑战&#xff0c;记住在每一天的开始&#xff0c;你都有机会给自己倒上一杯清新的力量&#xff0c;为心灵添一抹温暖。勇敢地面对生活的苦与甜…

10000 字详细讲解 Spring 中常用注解及其使用

如下图京东购物页面&#xff0c;当我们选择点击访问某一类商品时&#xff0c;就会向后端发起 HTTP 请求&#xff0c;当后端收到请求时&#xff0c;就会找到对应的代码逻辑对请求进行处理&#xff0c;那么&#xff0c;后端是如何来查找处理请求相对应的代码呢&#xff1f;答案就…

C++使用单链表实现一元多项式的加,乘操作

相邀再次喝酒 待 葡萄成熟透 但是命运入面 每个邂逅 一起走到了 某个路口 是敌与是友 各自也没有自由 位置变了 各有队友 首先&#xff0c;按照惯例&#xff0c;十分欢迎大家边听歌边观看本博客&#xff01;&#xff01; 最佳损友 - 陈奕迅 - 单曲 - 网易云音乐 (163.com) 一…

leetcode295. 数据流的中位数

class MedianFinder {//A为小根堆&#xff0c;B为大根堆List<Integer> A,B;public MedianFinder() {A new ArrayList<Integer>();B new ArrayList<Integer>();}public void addNum(int num) {int m A.size(),n B.size();if(m n){insert(B,num);int top …

开源模型 Prometheus 2 能够评估其他语言模型,其效果几乎与 GPT-4 相当

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

springboot使用研究

map-underscore-to-camel-case: true 开启驼峰命名 GetMapping("/userInfo")public Result<Users> userInfo(RequestHeader(name "Authorization") String token,HttpServletResponse response) {Map<String, Object> map JwtUtil.parseT…

Java | Spring框架|Bean的装配之注解配置

Spring | Bean的装配之 注解配置&#xff1a;简化配置的新标准 Spring框架的注解配置是近年来流行的配置方式&#xff0c;它通过在Java代码中使用注解来简化Bean的配置。这种方式减少了XML配置文件的使用&#xff0c;使得Bean的定义更加直观和简洁。 一、 使用注解定义Bean …

Problem 5: Whack-A-Mole打地鼠

实战题&#xff1a;打地鼠 内容如附件所示&#xff1a; 测试数据为:1,2,4,8,9,10,11,14 答案为&#xff1a;10,2,4 原始分布&#xff1a; 击打10号 击打2号 击打4号 要求&#xff0c;所示实例解以图示的方式给出&#xff0c;并且5组测试数据都需要测试&#xff0c;…

软件工程案例学习-图书管理系统-面向对象方法

文档编号&#xff1a;LMS_1 版 本 号&#xff1a;V1.0 ** ** ** ** ** ** 文档名称&#xff1a;需求分析规格说明书 项目名称&#xff1a;图书管理系统 项目负责人&#xff1a;计敏 胡杰 ** ** …

开式双比例泵控制放大器

比例泵PQ控制放大器的主要作用是通过接收来自控制器的信号&#xff0c;并将其转换为适当的电流信号&#xff0c;以驱动变量泵。这种控制方式可以实现对泵输出流量和压力的精确控制&#xff0c;从而实现节能和提高效率的目的。比例泵PQ控制放大器通常用于节能型泵控制系统中&…

【Linux系列】tail查询使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【6D位姿估计】ZebraPose 层次化分组策略 由粗到细的表面编码

前言 本文介绍6D位姿估计的方法ZebraPose&#xff0c;也可以称为六自由度物体姿态估计&#xff0c;输入单张图片&#xff0c;输出物体的三维位置和三维方向。 它来自CVPR2022的论文&#xff0c;通过层次化分组策略&#xff0c;高效地编码物体表面的信息。 ZebraPose提出了一…

运维自动化之 ansible

目录 一 常见的自动化运维工具 &#xff08;一&#xff09;有哪些常见的 自动化运维工具 &#xff08;二&#xff09;为什么后面都变成用 ansible 二 ansible 基本介绍 1&#xff0c; ansible 是什么 2&#xff0c;ansible能干什么 3&#xff0c;ansible 工作原…

Linux网络—PXE高效批量网络装机

目录 一、部署PXE远程安装服务 1、搭建PXE远程安装服务器 1&#xff09;安装并启用 TFTP 服务 2&#xff09;安装并启用 DHCP 服务 3&#xff09;准备 Linux 内核、初始化镜像文件 4&#xff09;准备 PXE 引导程序 5&#xff09;安装FTP服务&#xff0c;准备CentOS 7 安…

OpenCV 入门(一) —— OpenCV 基础

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

Springboot框架web开发实用功能-02

在些模块中汇总了一些web开发常用的配置和功能。 涉及的模块 springboot-common-config&#xff0c; 端口号&#xff1a;17000 Springboot框架web开发常用功能 Restful接口定义 查询参数 Data public class QueryParam {private String key;private String value; }Control…

MATLAB实现杜拉德公式和凯夫公式的计算固液混合料浆临界流速

MATLAB实现杜拉德公式和凯夫公式的计算固液混合料浆临界流速: 杜拉德公式是用来计算非均质固液混合料浆在输送管中的临界速度的公式&#xff0c;具体形式为&#xff1a; uL FL (2gD / (ρ0 - ρ1))^(1/2) 其中&#xff1a; uL&#xff1a;表示料浆的临界速度&#xff0c;…
最新文章