电子学会七级-数据结构-二叉树

电子学会七级-数据结构-二叉树

二叉树的存储
二叉树的顺序存储
【深基16.例1】淘汰赛
https://www.luogu.com.cn/problem/P4715

#include <bits/stdc++.h>
using namespace std;

const int N = 7;
int n;

struct Node {
	int country, power;
} t[2 << N + 10];

void build() {  // build the tree 两个队产生一个胜利对继续比赛 
	for (int i = n - 1; i > 0; --i) {
		int left = i << 1, right = i << 1 | 1;//left 左子树  right右子树 i<<1|1 =i*2+1 

		if(t[left].power < t[right].power){
			t[i].power =  t[right].power;
			t[i].country = t[right].country;
		} else {
			t[i].power =  t[left].power;
			t[i].country = t[left].country;
		}
	}
}

int main() {
	scanf("%d", &n);
	n = 1 << n;
	for (int i = 0; i < n; ++i) {
		scanf("%d", &t[n+i].power);//读入能力值 
		t[n+i].country = i + 1;//给国家编号 从1开始 
	}
	build();//构建比赛树 
	if(t[1].power == t[2].power)// 每个国家能力值不同 且 1==1 说明 1和2是一个国家 
		printf("%d\n", t[3].country);//亚军是第三个国家 
	else
		printf("%d\n", t[2].country);//1 2不是一个国家 亚军是2 

	return 0;
}

【深基16.例3】二叉树深度
https://www.luogu.com.cn/problem/P4913

#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r;//记录左右节点
}a[1005000];
int n;
int maxdep=-1;  //最大深度
void dfs(int cur_node,int step){
	if(cur_node==0){//节点为0 即为叶子节点 返回
		return ;
	}
	maxdep=max(maxdep,step);//找最大的深度
	dfs(a[cur_node].l,step+1);//搜索左节点,有的话深度就加1
	dfs(a[cur_node].r,step+1);//搜索右节点,同上
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].l>>a[i].r;//输入这个节点的左右节点
	}
	dfs(1,1);//从第一个节点开始,深度初始为1
	cout<<maxdep<<endl;
	return 0;
}

二叉树的链式存储
新二叉树
https://www.luogu.com.cn/problem/P1305

#include<bits/stdc++.h>
using namespace std;

//n节点数 root 根节点 L根节点左孩子  R根节点右孩子 
int n,root,L[100],R[100];
string s;//临时存储输入每行数据 

void preorder(int t){//先序遍历 
	if(t!='*'-'a'){//不是*号  当前子树必然有根 可以输出自己  
		cout<<char(t+'a');//输出自己 
		preorder(L[t]);//递归左子树 
		preorder(R[t]);//递归右子树 
	}
}

int main(){
	cin>>n;//输入节点数 
	for(int i=0;i<n;i++){//每个节点的左孩子和有孩子 
		cin>>s;
		if(!i){//第一个节点为根节点 
			root=s[0]-'a';
		}
		L[s[0]-'a']=s[1]-'a';//当前根节点左孩子 
		R[s[0]-'a']=s[2]-'a';//当前根节点右孩子 
	}
	preorder(root);//先序输出 
	return 0;
}

二叉树的遍历
新二叉树
https://www.luogu.com.cn/problem/P1305

#include<bits/stdc++.h>
using namespace std;

//n节点数 root 根节点 L根节点左孩子  R根节点右孩子 
int n,root,L[100],R[100];
string s;//临时存储输入每行数据 

void preorder(int t){//先序遍历 
	if(t!='*'-'a'){//不是*号  当前子树必然有根 可以输出自己  
		cout<<char(t+'a');//输出自己 
		preorder(L[t]);//递归左子树 
		preorder(R[t]);//递归右子树 
	}
}

int main(){
	cin>>n;//输入节点数 
	for(int i=0;i<n;i++){//每个节点的左孩子和有孩子 
		cin>>s;
		if(!i){//第一个节点为根节点 
			root=s[0]-'a';
		}
		L[s[0]-'a']=s[1]-'a';//当前根节点左孩子 
		R[s[0]-'a']=s[2]-'a';//当前根节点右孩子 
	}
	preorder(root);//先序输出 
	return 0;
}

https://www.luogu.com.cn/problem/P1030

字符串实现

#include<bits/stdc++.h>
using namespace std;
string a,b;
//m 中序  e后序 
void dfs(string m,string e) {
    if(m.size()>0){
    	char root=e[e.size()-1];//通过后序 找个字符 
    	int tmp=m.find(root);//找到 根在中序的位置 确定左子树和右子树 和左右子树个数 
        cout<<root;//根 
	    dfs(m.substr(0,tmp),e.substr(0,tmp));//左 取出 中序 后序 的左子树 
	    dfs(m.substr(tmp+1),e.substr(tmp,e.size()-1-tmp));//右 出 中序 后序 的右子树
    }
}
int main() {
//	freopen("C:/Users/Administrator/Downloads/P1030_1.in","r",stdin);
//	freopen("C:/Users/Administrator/Downloads/P1030_1_1.out","w",stdout);
    cin>>a>>b;
    dfs(a,b);
    return 0;
}

字符数组实现

#include<bits/stdc++.h>
using namespace std;
char a[101],b[101];

/*
	中序起点-left、终点-right 
	后续中 根的位置右端的位置偏移距离 t, b[right-t] 为根 
*/ 
void dfs(int left,int right,int t){
	cout<<b[right-t];//后续找根 输出根 
	for(int i=left;i<=right;i++){
		if(a[i]==b[right-t]){//中序中找到根 分成左右两部分 
			if(i!=left){//如果在中序根的位置不是起点 可以有左子树 
				dfs(left,i-1,t);//递归左子树  
			}
			if(i!=right){//如果在中序根的位置不是终点 可以有右子树
				dfs(i+1,right,t+1);//递归右子树 
			}
		}
	}
	return;
}
int main(){
	cin>>a;//中序 
	cin>>b;//后续 
	int n=strlen(a);//中序长度  
	dfs(0,n-1,0);//0~n-1 根在后续中最后一个位置 
}

https://www.luogu.com.cn/problem/UVA536

#include<string>
#include<iostream>
#include<stack>
using namespace std;
string inorder,preorder;
void dfs(string p,string i){//p为先序遍历,i为中序遍历。
	if(i.size()<=0)return;//判断是否还有字符。
	int root;
   	//在中序中寻找根
	for(int j=0;j<i.size();j++){
		if(i[j]==p[0]){//从前到后比较前序根在中序的位置 
			root=j;
		}
	}
	//左 右 根 
	dfs(p.substr(1,root),i.substr(0,root));//左子树第一个为根,要从位置“1”开始取。
	dfs(p.substr(root+1),i.substr(root+1));//substr(root+1),取出从root+1这个位置开始往后所有字符。
	cout<<p[0];//输出根。
}
int main(){
	while(cin>>preorder>>inorder){//多组数据。
		dfs(preorder,inorder);
		cout<<endl;//注意,要换行。
	}
	
}

先序和中序转后序遍历 hdu1710

http://acm.hdu.edu.cn/showproblem.php?pid=1710
算法竞赛入门到进阶 P68

[USACO3.4]美国血统 American Heritage
https://www.luogu.com.cn/problem/P1827

【深基16.例7】普通二叉树(简化版)
https://www.luogu.com.cn/problem/P5076
医院设置
https://www.luogu.com.cn/problem/P1364
遍历问题
https://www.luogu.com.cn/problem/P1229
[NOIP2004 普及组] FBI 树
https://www.luogu.com.cn/problem/P1087
[JLOI2009]二叉树问题
https://www.luogu.com.cn/problem/P3884
绘制二叉树
https://www.luogu.com.cn/problem/P1185

posted @ 2022-04-14 11:35  new-code  阅读(32)  评论(0)    收藏  举报