数据结构与算法之树的入门(二叉树)(三)

简介: 数据结构与算法之树的入门(二叉树)

七、二叉树的最大深度问题


需求:


给定一棵树,请计算树的最大深度(树的根节点到最远叶子结点的最长路径上的结点数)


add2332a8c1d4ec785e78a2e431535eb.png

上面这棵树的最大深度为4。


实现:


我们在1.4中创建的树上,添加如下的API求最大深度:


public int maxDepth() :计算整个树的最大深度


private int maxDepth(Node x): 计算指定树x的最大深度


实现步骤


1.如果根结点为空,则最大深度为0;


2.计算左子树的最大深度;

3.计算右子树的最大深度;

4.当前树的最大深度=左子树的最大深度和右子树的最大深度中的较大者+1


代码:

// 计算整个树的最大深度
public int maxDepth() {
  return maxDepth(root);
}
//计算指定树x的最大深度
private int maxDepth(Node x) {
  //1.如果根结点为空,则最大深度为0;
  if (x == null) {
    return 0;
  }
  int max = 0;
  int maxL = 0;
  int maxR = 0;
  //2.计算左子树的最大深度;
  if (x.left != null) {
    maxL = maxDepth(x.left);
  }
  //3.计算右子树的最大深度;
  if (x.right != null) {
    maxR = maxDepth(x.right);
  }
  //4.当前树的最大深度=左子树的最大深度和右子树的最大深度中的较大者+1
  max = maxL > maxR ? maxL + 1 : maxR + 1;
  return max;
}
//测试代码
public class Test {
  public static void main(String[] args) throws Exception {
    BinaryTree<String, String> bt = new BinaryTree<>();
    bt.put("E", "5");
    bt.put("B", "2");
    bt.put("G", "7");
    bt.put("A", "1");
    bt.put("D", "4");
    bt.put("F", "6");
    bt.put("H", "8");
    bt.put("C", "3");
    int i = bt.maxDepth();
    System.out.println(i);
  }
}

八、折纸问题


需求:


请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时 折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2 次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。


给定一 个输入参数N,代表纸条都从下边向上方连续对折N次,请从上到下打印所有折痕的方向 例如:N=1时,打印: down;N=2时,打印: down down up


9a57d8fe8c3142d58b574f5d2a4dea6f.png

分析:


我们把对折后的纸张翻过来,让粉色朝下,这时把第一次对折产生的折痕看做是根结点,那第二次对折产生的下折痕就是该结点的左子结点,而第二次对折产生的上折痕就是该结点的右子结点,这样我们就可以使用树型数据结构来描述对折后产生的折痕。


这棵树有这样的特点:


1.根结点为下折痕;

2.每一个结点的左子结点为下折痕;

3.每一个结点的右子结点为上折痕;


8ed42df6b08b455fb226331add2ddaf0.png

实现步骤:


1.定义结点类

2.构建深度为N的折痕树;

3.使用中序遍历,打印出树中所有结点的内容;


构建深度为N的折痕树:


1.第一次对折,只有一条折痕,创建根结点;

2.如果不是第一次对折,则使用队列保存根结点;

3.循环遍历队列:

3.1从队列中拿出一个结点;

3.2如果这个结点的左子结点不为空,则把这个左子结点添加到队列中;

3.3如果这个结点的右子结点不为空,则把这个右子结点添加到队列中;

3.4判断当前结点的左子结点和右子结点都不为空,如果是,则需要为当前结点创建一个值为down的左子结点,一个值为up的右子结点。


代码:


public class PaperFolding {
  public static void main(String[] args) {
    //构建折痕树
    Node tree = createTree(3);
    //遍历折痕树,并打印
    printTree(tree);
  }
  //3.使用中序遍历,打印出树中所有结点的内容;
  private static void printTree(Node tree) {
    if (tree==null){
      return;
    }
    printTree(tree.left);
    System.out.print(tree.item+",");
    printTree(tree.right);
  }
  //2.构建深度为N的折痕树;
  private static Node createTree(int N) {
      Node root = null;
    for (int i = 0; i <N ; i++) {
      if (i==0){
        //1.第一次对折,只有一条折痕,创建根结点;
        root = new Node("down",null,null);
      }else{
        //2.如果不是第一次对折,则使用队列保存根结点;
        Queue<Node> queue = new Queue<>();
        queue.enqueue(root);
        //3.循环遍历队列:
        while(!queue.isEmpty()){
          //3.1从队列中拿出一个结点;
          Node tmp = queue.dequeue();
          //3.2如果这个结点的左子结点不为空,则把这个左子结点添加到队列中;
          if (tmp.left!=null){
            queue.enqueue(tmp.left);
          }
          //3.3如果这个结点的右子结点不为空,则把这个右子结点添加到队列中;
          if (tmp.right!=null){
            queue.enqueue(tmp.right);
          }
          //3.4判断当前结点的左子结点和右子结点都不为空,如果是,则需要为当前结点创建一个值为down的左子结点,一个值为up的右子结点。
          if (tmp.left==null && tmp.right==null){
            tmp.left = new Node("down",null,null);
            tmp.right = new Node("up",null,null);
          }
        }
      }
    }
    return root;
  }
  //1.定义结点类
  private static class Node{
    //存储结点元素
    String item;
    //左子结点
    Node left;
    //右子结点
    Node right;
    public Node(String item, Node left, Node right) {
      this.item = item;
      this.left = left;
      this.right = right;
    }
  }
}


目录
相关文章
|
2月前
|
存储 算法
算法入门:专题二---滑动窗口(长度最小的子数组)类型题目攻克!
给定一个正整数数组和目标值target,找出总和大于等于target的最短连续子数组长度。利用滑动窗口(双指针)优化,维护窗口内元素和,通过单调性避免重复枚举,时间复杂度O(n)。当窗口和满足条件时收缩左边界,更新最小长度,最终返回结果。
|
2月前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
207 4
|
2月前
|
存储 算法
算法入门:专题一:双指针(有效三角形的个数)
给定一个数组,找出能组成三角形的三元组个数。利用“两边之和大于第三边”的性质,先排序,再用双指针优化。固定最大边,左右指针从区间两端向内移动,若两短边之和大于最长边,则中间所有组合均有效,时间复杂度由暴力的O(n³)降至O(n²)。
|
2月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
5月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
139 2
|
7月前
|
存储 机器学习/深度学习 算法
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty  敏感词
|
5月前
|
机器学习/深度学习 数据采集 算法
你天天听“数据挖掘”,可它到底在“挖”啥?——数据挖掘算法入门扫盲篇
你天天听“数据挖掘”,可它到底在“挖”啥?——数据挖掘算法入门扫盲篇
110 0
|
7月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
192 17
|
7月前
|
存储 监控 算法
局域网上网记录监控的 C# 基数树算法高效检索方案研究
在企业网络管理与信息安全领域,局域网上网记录监控是维护网络安全、规范网络行为的关键举措。随着企业网络数据量呈指数级增长,如何高效存储和检索上网记录数据成为亟待解决的核心问题。基数树(Trie 树)作为一种独特的数据结构,凭借其在字符串处理方面的卓越性能,为局域网上网记录监控提供了创新的解决方案。本文将深入剖析基数树算法的原理,并通过 C# 语言实现的代码示例,阐述其在局域网上网记录监控场景中的具体应用。
174 7
|
6月前
|
机器学习/深度学习 算法 搜索推荐
决策树算法如何读懂你的购物心理?一文看懂背后的科学
"你为什么总能收到刚好符合需求的商品推荐?你有没有好奇过,为什么刚浏览过的商品就出现了折扣通知?

热门文章

最新文章