二叉树专题学习(C++版) 基础的上机题

前言:

由于二叉树这一章的题型比较多,涉及到的递归程序也较多,所以单开一个随笔来记录这个学习过程,希望对读者有帮助。

理论知识基础

在二叉树的选择题中,常常会涉及到对于最多或最少结点、最大或最小高度、求叶子结点个数这几类经典的问题。

上机题

1.二叉树的建立和遍历

P1305 新二叉树

  • 这题考察输入每个结点和其左右子树,然后前序遍历

P4715 【深基16.例1】淘汰赛

  • 这题考察给你所有叶子结点,让你建立一颗满二叉树

L2-051 满树的遍历

  • dfs前序遍历树
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
vector<int>ve[100005];
map<int,int>cnt;

void dfs(int x)
{
	if(ve[x].size()==0) return ;
	for(auto t:ve[x])
	{
		cout<<" "<<t;
		dfs(t);
	
	}
}


void solve() {

	int n;
	int maxx=-1;
	cin >> n;
	int root=0;
	for (int i = 1; i <= n; i++)
	{
		int u; cin>>u;
		cnt[u]++;
		ve[u].push_back(i);
		if(u==0) root=i;
		
	}
		
	maxx=cnt[root];
	
	
	int flag=0;
	for(int i=1;i<=n;i++) {
		sort(ve[i].begin(),ve[i].end());
		if(ve[i].size()!=0 ) if(ve[i].size()!=maxx) flag=1; 
		
	}
	cout<<maxx<<" ";
	if(flag) cout<<"no";
	else cout<<"yes";
	cout<<endl;
	
	cout<<root;
	dfs(root);
	
		
}


signed main() {

	int t = 1;
	// cin>>t;
	while (t--) solve();

	return 0;
}

P4913 【深基16.例3】二叉树深度

  • 建立二叉树遍历求深度

L2-006 树的遍历

  • 通过中序和后序构建树,然后再层序输出
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
int po[35];
int ino[35];
vector<int>ans[50];


int  dfs(int l1, int r1, int l2, int r2) {
	for (int i = l2; i <= r2; i++) {
		if (ino[i] == po[r1]) { 
			int root = po[r1]; 

			int lc = dfs(l1, l1 + i - l2 - 1, l2, i - 1) ; //递归左子树
			int rc = dfs(l1 + i - l2, r1 - 1, i + 1, r2) ; //递归右子树
			if (lc) ans[root].push_back(lc);
			if (rc) ans[root].push_back(rc);

			return root;
		}
	}
	return 0;


}


void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> po[i];
	for (int i = 1; i <= n; i++) cin >> ino[i];
	dfs(1, n, 1, n);

	queue<int>q;
	q.push(po[n]);
	cout << po[n];
	while (q.size()) {
		int t = q.front();
		q.pop();
		for (auto i : ans[t]) {
			q.push(i);
			cout << " " << i;
		}


	}




}


signed main() {

	int t = 1;
	// cin>>t;
	while (t--) solve();

	return 0;
}

L2-038 病毒溯源

  • 最大深度,以及最小且最长的路径
#include <bits/stdc++.h>
using namespace std;
vector<int>bd[10005];
bool vis[10005];
int maxx = -1;
int root;
map<int, int>d; //用来找根节点,根节点入度为0
vector<int>road;
bool check;



void  dfslen(int x, int dep) { //递归找最大长度
	if (bd[x].size() == 0) maxx = max(dep, maxx);
	for (auto t : bd[x]) dfslen(t, dep + 1);
}

bool    dfs(int x,int dep)
{
	if(dep==maxx)
	{
		return 1;
	}
	bool res=0;
	for(auto t:bd[x])
	{
		if(dfs(t,dep+1)) {
			if(t<road[x]) road[x]=t;
			res=1;
		}
		
	}
	return res;
	
}

/*
void dfs(int x,int dep)
{
	if(dep==maxx) {
		check=1;
		return ;
	}
	check=0;
	for(auto t:bd[x])
	{
		dfs(t,dep+1);
		if(check){
			if(t<road[x]) road[x]=t;
		} 
	}
	

}*/



signed main() {

	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int x;
		cin >> x;
		while (x--) {
			int z;
			cin >> z;
			bd[i].push_back(z);
			d[z]++;
		}
	}

 	//寻找根节点
	for (int i = 0; i < n; i++) {
		if (d[i] == 0) {
			root = i;
			break;
		}
	}


	dfslen(root, 1);

		cout << maxx <<endl;
	road.resize(n);
	for(int i=0;i<n;i++) road[i]=1e9;
	
	dfs(root,1);
	
	int cur=root;
	cout<<root;
	while(road[cur]!=1e9)
	{
		cout<<" "<<road[cur];
		cur=road[cur];
	}
	





}

L2-035 完全二叉树的层序遍历

  • 通过后序遍历序列 建立层次遍历序列
#include <bits/stdc++.h>
#define int long long
using namespace std;
#define endl '\n'
int tree[100005];
int a[100005];
int p = 1;
int n;

void dfs(int x) {
	if (x <= n) {
		dfs(2 * x);
		dfs(2 * x + 1);
		tree[x] = a[p++];
	}
}



void solve() {


	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	dfs(1);

	cout << tree[1];
	for (int i = 2; i <= n; i++) {
		cout << " " << tree[i];
	}


}


signed main() {

	int t = 1;
	// cin>>t;
	while (t--) solve();

	return 0;
}

2.前序、中序、后序遍历的转换
给出了中序以后,给定前序或后序都可以确定唯一的一棵树。
不给出中序则无法确定。

P1827 [USACO3.4] 美国血统 American Heritage

  • 这题给出前序和中序求后序

P1030 [NOIP2001 普及组] 求先序排列

  • 这题给出中序和后序求前序

posted on 2024-10-31 20:48  swj2529411658  阅读(6)  评论(0编辑  收藏  举报

导航