首页 > 编程语言 >树的简单应用C++算法学习

树的简单应用C++算法学习

时间:2023-08-13 16:33:15浏览次数:56  
标签:Node lchild 结点 int C++ 学习 算法 二叉树 root

1、找树根和孩子

【题目描述】 给定一棵树,输出树的根root,孩子最多的结点max以及他的孩子。

【输入】 第一行:n(结点个数≤100),m(边数≤200)。

以下m行:每行两个结点x和y,表示y是x的孩子(x,y≤1000)。

【输出】 第一行:树根:root;

第二行:孩子最多的结点max;

第三行:max的孩子(按编号由小到输出)。

【输入样例】 8 7 4 1 4 2 1 3 1 5 2 6 2 7 2 8 【输出样例】 4 2 6 7 8

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int tree[105];
int main()
{
	int n,m,x,y;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>x>>y;
		tree[y]=x;// y的父亲结点是x
	}
	int root;
	for(int i=1;i<=n;i++)
	{
		if(tree[i]==0)// 父亲结点为0的结点是根节点
		{
			root=i;
			break;
		}
	}
	int maxt=0,sumt=0;
	for(int i=1;i<=n;i++)
	{
		int sum=0;// 孩子结点的个数
		for(int j=1;j<=n;j++)
		{
			if(tree[j]==i)sum++;// 对每一个结点i,寻找其孩子结点
		}
		if(sum>sumt)
		{
			sumt=sum;
			maxt=i;
		}
	}
	cout<<root<<"\n"<<maxt<<endl;
	for(int i=1;i<=n;i++)
	{
		if(tree[i]==maxt)
		{
			cout<<i<<" ";
		}
	}
	return 0;
}
2、求后序遍历

【题目描述】 输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列。

【输入】 共两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串,表示树的中序遍历。树的结点一律用小写字母表示。

【输出】 一行,表示树的后序遍历序列。

【输入样例】 abdec dbeac 【输出样例】 debca

#include<iostream>
#include<cstring>
using namespace std;

const int N=100000;
// 定义二叉树的结点类型
struct Node
{
	char data;
	Node* lchild;
	Node* rchild;
};
// 先序、中序、后序序列
char pre[N],in[N],post[N];
// 重建二叉树,递归方法
// 利用先序[preL,preR],中序[inL,inR]序列
Node* create(int preL,int preR,int inL,int inR)
{
	if(preL>preR)return NULL;//遍历完了
	Node *root=new Node;
	root->data=pre[preL];// 先序序列的第一个即为根结点
	int k;// 找到根节点在中序序列中的位置
	for(k=inL;k<=inR;k++)
	{
		if(in[k]==root->data)
		{
			break;
		}
	}
	int numLeft=k-inL; // 左子树的结点数量
	root->lchild=create(preL+1,preL+numLeft,inL,k-1);// 递归创建左子树
	root->rchild=create(preL+numLeft+1,preR,k+1,inR);// 递归创建右子树
	return root; // 返回根结点
}
// 二叉树的后序遍历 左-右-根 的顺序
void postOrder(Node* root)
{
	if(root==NULL)
		return;
	postOrder(root->lchild);// 先递归遍历左子树
	postOrder(root->rchild);// 先递归遍历右子树
	cout<<root->data; // 输出结点的值
}
int main()
{
	scanf("%s",pre);
	scanf("%s",in);
	int len=strlen(pre);
	Node *root=create(0,len-1,0,len-1);// 下标是从0开始的
	postOrder(root);
	return 0;
}
3、树的凹入表示法输出

【题目描述】 树的凹入表示法主要用于树的屏幕或打印输出,其表示的基本思想是兄弟间等长,一个结点的长度要不小于其子结点的长度。二叉树也可以这样表示,假设叶结点的长度为1,一个非叶结点的长度等于它的左右子树的长度之和。

一棵二叉树的一个结点用一个字母表示(无重复),输出时从根结点开始:

每行输出若干个结点字符(相同字符的个数等于该结点长度),

如果该结点有左子树就递归输出左子树;

如果该结点有右子树就递归输出右子树。

假定一棵二叉树一个结点用一个字符描述,现在给出先序和中序遍历的字符串,用树的凹入表示法输出该二叉树。

【输入】 两行,每行是由字母组成的字符串(一行的每个字符都是唯一的),分别表示二叉树的先序遍历和中序遍历的序列。

【输出】 行数等于该树的结点数,每行的字母相同。

【输入样例】 ABCDEFG CBDAFEG 【输出样例】 AAAA BB C D EE F G

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

const int N=100000;
struct Node
{
	char data;
	Node* lchild;
	Node* rchild;
};
char pre[N],in[N];
int cnt[N];
// 建树
Node* create(int preL,int preR,int inL,int inR)
{
	if(preL>preR)return NULL;
	Node *root=new Node;
	root->data=pre[preL];
	int k;
	for(k=inL;k<=inR;k++)
	{
		if(in[k]==root->data)
		{
			break;
		}
	}
	int numLeft=k-inL;
	root->lchild=create(preL+1,preL+numLeft,inL,k-1);
	root->rchild=create(preL+numLeft+1,preR,k+1,inR);
	return root;
}
// 计算每个结点的长度
int count(Node* root)
{
	if(root->lchild==NULL&&root->rchild==NULL)
	{
		cnt[root->data]=1;// 叶子结点的长度为1
		return 1;
	}
	int cntL=0,cntR=0;
	// 递归,求左、右子树的长度
	if(root->lchild!=NULL)
	{
		cntL=count(root->lchild);
	}
	if(root->rchild!=NULL)
	{
		cntR=count(root->rchild);
	}
	cnt[root->data]=cntL+cntR;//父节点的长度=左右子树长度之和
	return cntL+cntR;
}
int main()
{
	scanf("%s",pre);
	scanf("%s",in);
	int len=strlen(pre);
	Node *root=create(0,len-1,0,len-1);
	count(root);
	// 对应每一个结点,输出其长度个元素值
	for(int i=0;i<len;i++)
	{
		for(int j=0;j<cnt[pre[i]];j++)
		{
			cout<<pre[i];
		}
		cout<<endl;
	}
	return 0;
}
4、查找二叉树

题目描述】 已知一棵二叉树用邻接表结构存储,中序查找二叉树中值为x的结点,并指出是第几个结点。例:如图二叉树的数据文件的数据格式如下:

【输入】 第一行n为二叉树的结点个树,n<=100;第二行x表示要查找的结点的值;以下第一列数据是各结点的值,第二列数据是左儿子结点编号,第三列数据是右儿子结点编号。

【输出】 一个数即查找的结点编号。

【输入样例】 7 15 5 2 3 12 4 5 10 0 0 29 0 0 15 6 7 8 0 0 23 0 0 【输出样例】 4

#include<iostream>
using namespace std;

const int N=100000;
struct Node
{
	int data;
	int lchild;
	int rchild;
}arr[N];
bool flag[N];
int val;
int x=0;
// 按照左根右顺序
void in(int root)
{
	if(arr[root].lchild>0)
	{
		in(arr[root].lchild);	
	}	
	x++;// 遍历到的结点数加1
	if(arr[root].data==val)
	{
		cout<<x;
		return;
	}
	if(arr[root].rchild>0)
	{
		in(arr[root].rchild);
	}
}
int main()
{
	int n;
	cin>>n>>val;
	for(int i=1;i<=n;i++)
	{
		cin>>arr[i].data>>arr[i].lchild>>arr[i].rchild;
		flag[arr[i].lchild]=true;// 都不是树根 
		flag[arr[i].rchild]=true;
	}
	int rt;
	for(int i=1;i<=n;i++)
	{
		if(!flag[i])
		{
		    rt=i;// 找到树根
		    break; 
		}
	}
	in(rt);
	return 0;
}

标签:Node,lchild,结点,int,C++,学习,算法,二叉树,root
From: https://blog.51cto.com/u_16200950/7067891

相关文章

  • 人工智能革命:机器学习如何改变营销的面貌
    市场营销、营销分析、新技术、生产力、社交媒体、战略、技能提升和专业发展你准备好认识你的新营销超级英雄了吗?向人工智能(AI)问好!这项改变游戏规则的技术正在改变从自动驾驶汽车到虚拟助手的一切,现在它正在席卷营销界。在机器学习算法的帮助下,人工智能使营销人员能够以前所未有......
  • 查找算法——顺序查找
    基于无序链表的顺序查找:在查找中我们一个一个地顺序遍历符号表中的所有键并使用equals()方法来寻找与被查找的键匹配的键。无序链表查找的性能上面get()方法中查找第一个键需要1次比较,查找第二个需要2次比较,如此这般,平均比较次数为(1+2+...+N)/N,也就是(N+1)/2~N/2。比较的总次数......
  • 《算法》——深度优先搜索
    定义:图是由一组顶点和一组能够将两个顶点相连的边组成的相关术语:当两个顶点通过一条边相连时,我们称这两个顶点是相邻的,并称这条边依附于这两个顶点某个顶点的度数即为依附于它的边的总数。子图是由一幅图的所有边的一个子集(以及它们所依附的所有的顶点)组成的图。在图......
  • 《算法》——广度优先搜索与找寻找路径
    单点路径问题在图的处理领域中十分重要,从输入流中读取一个图从从命令行得到一个起点,然后打印从起点到与它连通的每个顶点之间的一条路径。深度优先找路径下面扩展了尝试优先搜索代码,添加一一个实例变量edgeTo[]整型数组来起到Tremaux搜索中绳子的作用,这个数组可以找到从每个与......
  • Linux 学习十章
    第一章:Linux基础概念Linux的历史与发展Linux发行版及其特点常用的Linux命令行工具和基本操作第二章:文件和目录管理Linux文件系统的层级结构常用的文件和目录操作命令文件权限和所有权管理第三章:文本编辑器和Shell脚本常用的文本编辑器,如Vi或NanoShell脚本编程基础常用的Shell脚本语......
  • 分治算法——241. 为运算表达式设计优先级
    分治思路:对于一个算式来说,总是可以根据运算符分为左右两部分算式,接着分别计算结果并合并;每一个结果都是一个数组,包含这个算式的所有可能结果,计算时将左右两部分排列组合;递归的终点是字符串是纯数字(即分到一个算式中只剩下一个数字),直接返回。 比如示例中的2*3-4*5,有下面的......
  • Raft 算法
    论文《InSearchofanUnderstandableConsensusAlgorithm》,发表于2014年相比于Paxos,Raft最大的特性就是易于理解。为了达到这个目标,Raft主要做了两方面的事情:问题分解:把共识算法分为三个子问题,分别是领导者选举(leaderlection)、日志复制(logreplication)、安全性(......
  • C++STL库 二分查找,以及对set集合进行二分查找,来源于”leetcode7022. 限制条件下元素之
    C++的头文件<algorithm>中有用于二分查找的函数,lower_bound()、upper_bound()以及binary_search():lower_bound():返回大于等于目标值的第一个位置upper_bound():返回大于目标值的第一个位置,binary_search():若目标值存在则返回true,否则返回false参数列表:(起始位置,结束位置,目标值) ......
  • 文心一言 VS 讯飞星火 VS chatgpt (75)-- 算法导论7.2 4题
    四、如果用go语言,银行一般会按照交易时间来记录某一账户的交易情况。但是,很多人却喜欢收到的银行对账单是按照支票号码的顺序来排列的。这是因为,人们通常都是按照支票号码的顺序来开出支票的,而商人也通常都是根据支票编号的顺序兑付支票。这一问题是将按交易时间排序的序列转换成按......
  • 通过一个实例的例子,学习 SAP Fiori 应用中的 Draft Handling(草稿机制)
    SAPFiori应用里的DraftHandling(草稿处理)是一种机制,用于在SAP业务数据的编辑过程中,实时保存未提交的更改。这样的机制允许用户在多个会话或者繁琐的表单填写步骤中,逐渐构建和修改数据,并在需要时将其提交。DraftHandling在SAPFiori应用中起到重要的作用,可以在不中断现有......