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

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

五、二叉树的基础遍历


很多情况下,我们可能需要像遍历数组数组一样,遍历树,从而拿出树中存储的每一个元素,由于树状结构和线性结构不一样,它没有办法从头开始依次向后遍历,所以存在如何遍历,也就是按照什么样的搜索路径进行遍历的问题


69be08eba24c4293b4435d16b8f1afd0.png

我们把树简单的画作上图中的样子,由一个根节点、一个左子树、一个右子树组成,那么按照根节点什么时候被访


问,我们可以把二叉树的遍历分为以下三种方式:


1.前序遍历;

先访问根结点,然后再访问左子树,最后访问右子树

2.中序遍历;

先访问左子树,中间访问根节点,最后访问右子树

3.后序遍历;

先访问左子树,再访问右子树,最后访问根节点


如果我们分别对下面的树使用三种遍历方式进行遍历,得到的结果如下:


0c5bcd26a443416dbad8c38198bed612.png

5.1.前序遍历


我们在4.4中创建的树上,添加前序遍历的API:


public Queue<Key> preErgodic() :使用前序遍历,获取整个树中的所有键
private void preErgodic(Node x,Queue<Key> keys) :使用前序遍历,把指定树x中的所有键放入到keys队列中

实现过程中,我们通过前序遍历,把,把每个结点的键取出,放入到队列中返回即可。

实现步骤:


1.把当前结点的key放入到队列中;

2.找到当前结点的左子树,如果不为空,递归遍历左子树

3.找到当前结点的右子树,如果不为空,递归遍历右子树


代码:

// 使用前序遍历,获取整个树中的所有键
public Queue<Key> preErgodic(){
  Queue<Key> keys = new Queue<>();
  preErgodic(root,keys);
  return keys;
}
//使用前序遍历,把指定树x中的所有键放入到keys队列中
private void preErgodic(Node x,Queue<Key> keys){
  if (x==null){
  return;
  }
  //1.把当前结点的key放入到队列中;
  keys.enqueue(x.key);
  //2.找到当前结点的左子树,如果不为空,递归遍历左子树
  if (x.left!=null){
    preErgodic(x.left,keys);
  }
  //3.找到当前结点的右子树,如果不为空,递归遍历右子树
  if (x.right!=null){
    preErgodic(x.right,keys);
  }
}
//测试代码
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");
    Queue<String> queue = bt.preErgodic();
    for (String key : queue) {
      System.out.println(key+"="+bt.get(key));
    }
  }
}

5.2.中序遍历


我们在4.4中创建的树上,添加前序遍历的API:


public Queue<Key> midErgodic() :使用中序遍历,获取整个树中的所有键
private void midErgodic(Node x,Queue<Key> keys) :使用中序遍历,把指定树x中的所有键放入到keys队列中


实现步骤:


1.找到当前结点的左子树,如果不为空,递归遍历左子树


2.把当前结点的key放入到队列中;

3.找到当前结点的右子树,如果不为空,递归遍历右子树


代码:

//使用中序遍历,获取整个树中的所有键
public Queue<Key> midErgodic(){
  Queue<Key> keys = new Queue<>();
  midErgodic(root,keys);
  return keys;
}
//使用中序遍历,把指定树x中的所有键放入到keys队列中
private void midErgodic(Node x,Queue<Key> keys){
  if (x==null){
    return;
  }
  //1.找到当前结点的左子树,如果不为空,递归遍历左子树
  if (x.left!=null){
    midErgodic(x.left,keys);
  }
  //2.把当前结点的key放入到队列中;
  keys.enqueue(x.key);
  //3.找到当前结点的右子树,如果不为空,递归遍历右子树
  if (x.right!=null){
    midErgodic(x.right,keys);
  }
}
//测试代码
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");
    Queue<String> queue = bt.midErgodic();
    for (String key : queue) {
      System.out.println(key+"="+bt.get(key));
    }
  }
}

5.3.后序遍历


我们在4.4中创建的树上,添加前序遍历的API:


public Queue<Key> afterErgodic() :使用后序遍历,获取整个树中的所有键


private void afterErgodic(Node x,Queue<Key> keys) :使用后序遍历,把指定树x中的所有键放入到keys队列中


实现步骤:


1.找到当前结点的左子树,如果不为空,递归遍历左子树

2.找到当前结点的右子树,如果不为空,递归遍历右子树

3.把当前结点的key放入到队列中;


代码:

//使用后序遍历,获取整个树中的所有键
public Queue<Key> afterErgodic(){
  Queue<Key> keys = new Queue<>();
  afterErgodic(root,keys);
  return keys;
}
//使用后序遍历,把指定树x中的所有键放入到keys队列中
private void afterErgodic(Node x,Queue<Key> keys){
  if (x==null){
    return;
  }
  //1.找到当前结点的左子树,如果不为空,递归遍历左子树
  if (x.left!=null){
    afterErgodic(x.left,keys);
  }
  //2.找到当前结点的右子树,如果不为空,递归遍历右子树
  if (x.right!=null){
    afterErgodic(x.right,keys);
  }
  //3.把当前结点的key放入到队列中;
  keys.enqueue(x.key);
}
//测试代码
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");
    Queue<String> queue = bt.afterErgodic();
    for (String key : queue) {
      System.out.println(key+"="+bt.get(key));
    }
  }
}

六、二叉树的层序遍历


所谓的层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值,有二叉树如下:


230856d351c84b96b33812e2bbc00c29.png

那么层序遍历的结果是: EBGADFHC


我们在4.4中创建的树上,添加层序遍历的API:


public Queue<Key> layerErgodic() :使用层序遍历,获取整个树中的所有键


实现步骤:


1.创建队列,存储每一层的结点;

2.使用循环从队列中弹出一个结点:

2.1获取当前结点的key;

2.2如果当前结点的左子结点不为空,则把左子结点放入到队列中

2.3如果当前结点的右子结点不为空,则把右子结点放入到队列中

08aacb7628434d4bab53e7b20e44fc7a.png

16592a2dd58d43aaad3a9855074cba7c.png

代码:

// 使用层序遍历得到树中所有的键
public Queue<Key> layerErgodic(){
  Queue<Key> keys = new Queue<>();
  Queue<Node> nodes = new Queue<>();
  nodes.enqueue(root);
  while(!nodes.isEmpty()){
    Node x = nodes.dequeue();
    keys.enqueue(x.key);
    if (x.left!=null){
      nodes.enqueue(x.left);
    }
    if (x.right!=null){
      nodes.enqueue(x.right);
    }
  }
  return keys;
}
//测试代码
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");
    Queue<String> queue = bt.layerErgodic();
    for (String key : queue) {
      System.out.println(key+"="+bt.get(key));
    }
  }
}


目录
相关文章
|
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月前
|
机器学习/深度学习 算法 搜索推荐
决策树算法如何读懂你的购物心理?一文看懂背后的科学
"你为什么总能收到刚好符合需求的商品推荐?你有没有好奇过,为什么刚浏览过的商品就出现了折扣通知?

热门文章

最新文章