二叉树初探

1|0二叉树初探

1|1完美二叉树

  • 理论基础

    • 完美二叉树,即层数为 h,而总结点数为 2h1

    • 对于每个结点 x ,左节点为 x×2,右节点为 x×2+1

    • 显然可以用递归遍历。

  • 存储方式

    • for (int i = 0; i < 1 << n; i++) { cin >> tree[i + (1 << n)]; }
  • 递归遍历

    • void (int x) { if (x >= 1 << n)//即到达叶子节点 return; dfs(x * 2); dfs(x * 2 + 1); }
  • 例题

1|2二叉树深度

有一个 n(n106) 个结点的二叉树。给出每个结点的两个子结点编号(均不超过 n),建立一棵二叉树(根节点的编号为 1),如果是叶子结点,则输入 0 0

建好这棵二叉树之后,请求出它的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。

1|3输入格式

第一行一个整数 n,表示结点数。

之后 n 行,第 i 行两个整数 lr,分别表示结点 i 的左右子结点编号。若 l=0 则表示无左子结点,r=0 同理。

1|4输出格式

一个整数,表示最大结点深度。

1|5样例 #1

1|0样例输入 #1

7 2 7 3 6 4 5 0 0 0 0 0 0 0 0

1|0样例输出 #1

4
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 2e5 + 7; int l[N], r[N]; int n; int dfs(int x) { if (!x) { return 0; } return max(dfs(l[x]), dfs(r[x])) + 1; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n; for (int i = 1; i <= n; i++) { cin >> l[i] >> r[i]; } cout << dfs(1); return 0; }

1|6二叉树的遍历

Snipaste-2023-11-22-23-38-08.png

1|0层次遍历

即BFS。

1 2 7 3 6 4 5

1|0深度优先遍历

  • 前序遍历

    • 先访问根节点,再遍历左子树,最后遍历右子树。

    • void pre_order(int x) { printf("%d ", x); if (t[x].left) pre_order(t[x].left); if (t[x].right) pre_order(t[x].right); }
    • 1 2 3 4 5 6 7

  • 中序遍历

    • 先遍历左子树,再访问根节点,最后遍历右子树。

    • void pre_order(int x) { if (t[x].left) pre_order(t[x].left); printf("%d ", x); if (t[x].right) pre_order(t[x].right); }
    • 4 3 5 2 6 1 7

  • 后续遍历

    • 先遍历左子树,再遍历右子树,最后访问根节点。

    • void pre_order(int x) { if (t[x].left) pre_order(t[x].left); if (t[x].right) pre_order(t[x].right); printf("%d ", x); }
    • 4 5 3 6 2 7 1

  • 美国血统

    • 思路

      • 通过前序遍历找到当前二叉树的根(即前序遍历中第一个位置的值)。
      • 然后可以在中序遍历中找出当前二叉树根所在的位置,此时可以得到左子树和右子树的大小,从而递归。
    • 例子

      • 前序遍历
        • 1 2 3 4 5 6 7
      • 中序遍历
        • 4 3 5 2 6 1 7
      • 第一次,在前序遍历中找到 1,然后在中序遍历中找 1 的位置,显然 4 3 5 2 6 在以 1 为根的左子树内,而 7 在以 1 为根的右子树内,从而提取左右两个区间进行递归。
    • 代码

      • void build(int l1, int r1, int l2, int r2) { for (int i = l2; i <= r2; i++) { if (a[l1] == b[i]) { build(l1 + 1, l1 + i - l2, l2, i - 1); build(l1 + i - l2 + 1, r1, i + 1, r2); cout << a[l1]; } } }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17850636.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示