二叉树从入门到AC(2)深度与层次遍历


前言

不知道在上一篇二叉树从入门到AC(1)构建和前中后序遍历
有没有人察觉一个问题,
在这里插入图片描述

在一开始的二叉树构建中,只要输入前序(叶子结点需加0 0)就可以确定一颗二叉树,而后半段又说只有前序和后序遍历无法确定一颗二叉树,这不是矛盾吗?
实际上,这里的代码构建的是满二叉树:在这里插入图片描述
而单纯的前序和后序确实是无法构建唯一二叉树的,因为我们可能会遇到一些特殊情况。
我们来看看下图:
在这里插入图片描述
我们来写一下他的前序遍历:
A B DE C FG
我们会发现一个尴尬的情况,对比下图,结构不一样,前序排列居然,完全一样。
在这里插入图片描述
所以单一的前序,本身不足以作为构建二叉树的条件,至于为什么前序和后序无法确定唯一二叉树,理由同上,可以多做几组不同的实验很好得出结论。

一、二叉树的深度

首先,二叉树的深度的定义,我们沿用leetcode的定义:
在这里插入图片描述
说白了就是一个梗:这波你在第几层,找到在大气层的选手输出层数即可。
那么算法应该很简单就能构思了,我们既然能遍历完这棵二叉树,那么在递归中使用一个MAX始终保存每个叶子结点的深度的最大值即可。
例题:
假设根恒为1号结点,
输入:n,然后n行输入n对儿子结点的编号,叶子结点输入为0。
输出:该二叉树的深度。
例如
在这里插入图片描述
Input:
5
2 3
4 5
0 0
0 0
0 0
Output:
4
可以理解为 第i行的两个数,分别为第i号结点的左右子结点
思路:
题意表明第i点的左右子结点编号分别为f[i][0] ,f[i][1]
结构体加DFS遍历
运用结构体储存遍历的两个方向
用DFS的算法思路不停地一插到底。
题解:

#include<stdio.h>
int n, max;
struct node {
    int left;
    int right;
}BTtree[1000003];//开个足够大的空间
int Max(int a,int b)
{
    if(a>b)
        return a;
    else
        return b;
}
void DFS(int id, int deep) {
    max = Max(max, deep);//记忆化搜索保留最大值
    if (id == 0) return ;//到达叶子结点时停止向下
    DFS(BTtree[id].left, deep+1);//向左遍历
    DFS(BTtree[id].right, deep+1);//向右遍历
}
int main() {
    int i=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
		scanf("%d %d",&BTtree[i].left,&BTtree[i].right);   //输入该结点的左结点和右结点
	}
    DFS(1, 1);//从1号结点出发,初始深度为1
    printf("%d",max);
    return 0;
}

到这里,可以发现,DFS仿佛成为了二叉树的核心算法。事实上,面对一个普通的线性表,我们通常可以用循环处理掉,而二叉树结构天生便与DFS搭档,因为线性表通常不需要DFS,更复杂的图和树会让DFS递归运算时间指数级爆炸,只有二叉树和DFS搭配使用才看起来一切刚刚好!
那么DFS一招鲜足够了吗?其实还有一种遍历,较之前中后序的递归演绎更直观,DFS同时也不再好使:层次遍历。

二、层次遍历

二叉树的层次遍历即按层次,以从上至下从左至右的顺序进行遍历。
在这里插入图片描述
以此二叉树为例
层次遍历即:ABCDEFG
这也是最直观好理解的遍历方式。
思路:
与前三种遍历运用的DFS栈式思路不同,这种一层层均匀向外拓展的遍历方式可以让我们想到一个东西:BFS,而BFS与DFS核心的区别便是,BFS则需要使用一个队列来进行维护。
所以在层次遍历中,我们将使用队列为结构。
在这里插入图片描述
这边先通俗地解释二者的区别:DFS是栈式思路,到了非叶子结点不会先输出而是往下接着搜索,等到输出这个点时已经一层层return回来了,满足first in last out。而BFS是利用队列先进先出,比如上图,按照层次遍历,读到的就地直接输出了。
具体算法:若该点非叶子结点,输出,将其下一层子结点排入队列。
我们可以模拟一下上图的情况:
队列:1.a入队 并放入子结点b c
2.b入队,放入子结点d e
3.c入队,放入子结点f g
如此反复,按先后顺序输出这个队列,即可得到层次遍历结果。
样例:
在这里插入图片描述
输入输出范例:
在这里插入图片描述

代码:

#include<stdio.h>
#include<stdlib.h>

typedef struct BTNode
{
    int data;
    struct BTNode *Left;
    struct BTNode *Right;
}Node;


//创建二叉树,按前序输入
Node* createBTree()
{
    Node *p;
    int ch;
	//printf("输入data");
    scanf("%d",&ch);
    if(ch == 0)     //如果到了叶子节点,接下来的左、右子树分别赋值为0
    {
        p = NULL;
    }
    else
    {
        p = (Node*)malloc(sizeof(Node));
        p->data = ch;
        p->Left  = createBTree();  //递归创建左子树
        p->Right = createBTree();  //递归创建右子树
    }
    return p;
}
int main()
{
	int i=0, ans[101] ,count=0,k=0,n=1;
	int Front = 0, Rear = 1;
    Node *root = NULL;
    Node *q[101],*v;
    root = createBTree();
    q[0] = root;
    while(Front <Rear){
        v= q[Front++];
        ans[count++] = v->data;
        if(v->Left != NULL) q[Rear++] = v->Left; //把左子结点放入队列
        if(v->Right != NULL) q[Rear++] = v->Right;//把右子结点放入队列
    }
     for(i = 0; i < count; i++)//输出层次遍历
        {
                k++;
                printf("%d ",ans[i]);
                if(k==n)//只是美观
                {
                    printf("\n");
                    n*=2;
                    k=0;
                }
            }
 return 0;
 }

相关文章目录

二叉树从入门到AC(1)构建和前中后序遍历
DFS与排列组合(C语言描述)#1
DFS与排列组合(C语言描述)#2

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值