二叉树是一种特殊的树,每次分支不超过两部分。对于二叉树的存储,可以分为两种情况讨论。

1.对于完美二叉树而言,即除了最后一层以外每个节点都有两个叶子节点的二叉树,适合使用数组存储,因为我们容易发现若从上到下,从左到右从1开始为每个节点分配编号,对于每个叶子节点i,其左儿子编号为2*i,右儿子编号为2*i+1,相当便于查找。

举个例子

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

题目描述

有 2^n(n7) 个国家参加世界杯决赛圈且进入淘汰赛环节。我经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。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;
}

 

posted on 2021-07-21 10:11  雪之下雪乃天下第一  阅读(56)  评论(0编辑  收藏  举报