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

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

五、二叉树的基础遍历


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


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));
    }
  }
}


目录
相关文章
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
59 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
49 2
|
2月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
1天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
1月前
|
算法 数据安全/隐私保护 计算机视觉
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
|
1月前
|
算法 数据可视化 安全
基于DWA优化算法的机器人路径规划matlab仿真
本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
147 68
|
1月前
|
算法 数据安全/隐私保护
室内障碍物射线追踪算法matlab模拟仿真
### 简介 本项目展示了室内障碍物射线追踪算法在无线通信中的应用。通过Matlab 2022a实现,包含完整程序运行效果(无水印),支持增加发射点和室内墙壁设置。核心代码配有详细中文注释及操作视频。该算法基于几何光学原理,模拟信号在复杂室内环境中的传播路径与强度,涵盖场景建模、射线发射、传播及接收点场强计算等步骤,为无线网络规划提供重要依据。
|
2天前
|
传感器 算法 物联网
基于粒子群算法的网络最优节点部署优化matlab仿真
本项目基于粒子群优化(PSO)算法,实现WSN网络节点的最优部署,以最大化节点覆盖范围。使用MATLAB2022A进行开发与测试,展示了优化后的节点分布及其覆盖范围。核心代码通过定义目标函数和约束条件,利用PSO算法迭代搜索最佳节点位置,并绘制优化结果图。PSO算法灵感源于鸟群觅食行为,适用于连续和离散空间的优化问题,在通信网络、物联网等领域有广泛应用。该算法通过模拟粒子群体智慧,高效逼近最优解,提升网络性能。