当前位置 : 主页 > 编程语言 > c语言 >

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

来源:互联网 收集:自由互联 发布时间:2023-08-25
1、找树根和孩子 【题目描述】给定一棵树,输出树的根root,孩子最多的结点max以及他的孩子。 【输入】第一行:n(结点个数≤100),m(边数≤200)。 以下m行:每行两个结点x和y,表
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;
}
网友评论