二叉树是一种特殊的树,每次分支不超过两部分。对于二叉树的存储,可以分为两种情况讨论。
1.对于完美二叉树而言,即除了最后一层以外每个节点都有两个叶子节点的二叉树,适合使用数组存储,因为我们容易发现若从上到下,从左到右从1开始为每个节点分配编号,对于每个叶子节点i,其左儿子编号为2*i,右儿子编号为2*i+1,相当便于查找。
举个例子
P4715 【深基16.例1】淘汰赛
题目描述
有 2^n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。我经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。给出各个国家的能力值,请问亚军是哪个国家?
输入格式
无
输出格式
无
输入输出样例
输入 #1
3
4 2 3 1 10 5 9 7
输出 #1
1
这题明显只要建立一棵完美二叉树,每个节点分别存储胜利者以及能力值,利用dfs即可解决。
代码如下。
#include<iostream> #include<cstdio> using namespace std; int value[300],winner[300];//每一层二叉树胜利者及能力值 int n; void dfs(int x){ if(x>=(1<<n))return; dfs(2*x); dfs(2*x+1); if(value[2*x]>value[2*x+1]){ winner[x]=winner[2*x]; value[x]=value[2*x]; } else{ winner[x]=winner[2*x+1]; value[x]=value[2*x+1]; } } int main(){ scanf("%d",&n); for(int i=0;i<(1<<n);i++){ int m; scanf("%d",&m); value[i+(1<<n)]=m; winner[i+(1<<n)]=i+1; } dfs(1); printf("%d",value[2]<value[3]?winner[2]:winner[3]); return 0; }
2.一些非完全二叉树可能深度很大,最极端的情况为其退化为一条链,无法用数组存储,因为所需长度高达2^n,故而采用结构体的方式存储。
举个例子
P4913 【深基16.例3】二叉树深度
题目描述
给出每个节点的两个儿子节点,建立一棵二叉树(根节点为 11),如果是叶子节点,则输入0 0
。建好树后希望知道这棵二叉树的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。
最多有 10^6 个结点。
输入格式
无
输出格式
无
输入输出样例
输入 #1
7 2 7 3 6 4 5 0 0 0 0 0 0 0 0
输出 #1
4
我们对每个节点定义两个成员变量,left表示左儿子,right表示右儿子,dfs函数返回节点的深度。
代码如下所示
#include<iostream> #include<cstdio> using namespace std; struct node{ int l,r; }t[1000005]; int n; void build(){ for(int i=1;i<=n;i++){ int x,y; scanf("%d %d",&x,&y); t[i].l=x; t[i].r=y; } } int dfs(int x){ if(x==0){ return 0; } return max(dfs(t[x].l),dfs(t[x].r))+1; } int main(){ cin>>n; build(); cout<<dfs(1)<<endl; return 0; }