树的前中后序以及广度优先搜索和深度优先搜索

news2024/11/29 3:46:03

文章目录

  • 基本概念
  • 定义一棵树
  • 前序遍历
  • 中序遍历
  • 后序遍历
  • BFS广度优先遍历
  • DFS深度优先遍历

基本概念

树是一个有n个有限节点组成一个具有层次关系的集合,每个节点有0个或者多个子节点,没有父节点的节点称为根节点,也就是说除了根节点以外每个节点都有父节点,并且有且只有一个。

树的种类比较多,有二叉树,红黑树,AVL树,B树,哈夫曼树,字典树等等。
在这里插入图片描述
同时,树有比较多的需要掌握的概念

结点的度:一个结点含有的子结点的个数称为该结点的度;

叶结点或终端结点:度为0的结点称为叶结点;

非终端结点或分支结点:度不为0的结点;

双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;

孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点;

兄弟结点:具有相同父结点的结点互称为兄弟结点;

树的度:一棵树中,最大的结点的度称为树的度;

结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;

树的高度或深度:树中结点的最大层次;

堂兄弟结点:双亲在同一层的结点互为堂兄弟;

结点的祖先:从根到该结点所经分支上的所有结点;

子孙:以某结点为根的子树中任一结点都称为该结点的子孙。

森林:由m(m>=0)棵互不相交的树的集合称为森林;

无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;

有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;

二叉树:每个节点最多含有两个子树的树称为二叉树;

完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h
层所有的结点都连续集中在最左边,这就是完全二叉树

满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。

哈夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树;

定义一棵树

public class TreeNode {
    public int val;
     public TreeNode left;
     public TreeNode right;
 
     public TreeNode(int x) {
         val = x;
     }
 
    public TreeNode() {
}

前序遍历

他的访问顺序是:根节点→左子树→右子树
访问顺序为:A-B-C-D-E-F
在这里插入图片描述

	//递归写法
		public static void preOrder(TreeNode tree) {
            if (tree == null)
                return;
            System.out.printf(tree.val + "");
            preOrder(tree.left);
            preOrder(tree.right);
        }
   //非递归写法
    public static void preOrder(TreeNode tree) {
           if (tree == null)
               return;
           Stack<TreeNode> q1 = new Stack<>();
           q1.push(tree);//压栈
           while (!q1.empty()) {
               TreeNode t1 = q1.pop();//出栈
               System.out.println(t1.val);
               if (t1.right != null) {
                    q1.push(t1.right);
                }
                if (t1.left != null) {
                    q1.push(t1.left);
                }
            }
        }

中序遍历

他的访问顺序是:左子树→根节点→右子树

所以下图中序遍历的结果是:C-B-D-A-E-F

访问顺序如下
在这里插入图片描述

	//递归写法
	 public static void inOrderTraversal(TreeNode node) {
           if (node == null)
               return;
           inOrderTraversal(node.left);
           System.out.println(node.val);
           inOrderTraversal(node.right);
       }
        //非递归的写法
        public static void inOrderTraversal(TreeNode tree) {
           Stack<TreeNode> stack = new Stack<>();
           while (tree != null || !stack.isEmpty()) {
               while (tree != null) {
                   stack.push(tree);
                   tree = tree.left;
               }
               if (!stack.isEmpty()) {
                   tree = stack.pop();
                    System.out.println(tree.val);
                    tree = tree.right;
                }
            }
      }

后序遍历

他的访问顺序是:左子树→右子树→根节点

所以上图前序遍历的结果是:C-D-B-F-E-A
在这里插入图片描述

//递归写法
	 public static void postOrder(TreeNode tree) {
           if (tree == null)
                    return;
            postOrder(tree.left);
            postOrder(tree.right);
            System.out.println(tree.val);
        }
    //非递归的写法

        public static void postOrder(TreeNode tree) {
           if (tree == null)
               return;
         Stack<TreeNode> s1 = new Stack<>();
         Stack<TreeNode> s2 = new Stack<>();
         s1.push(tree);
         while (!s1.isEmpty()) {
             tree = s1.pop();
             s2.push(tree);
              if (tree.left != null) {
                  s1.push(tree.left);
              }
              if (tree.right != null) {
                  s1.push(tree.right);
              }
          }
          while (!s2.isEmpty()) {
              System.out.print(s2.pop().val + " ");
          }
      }
     //  或者

        public static void postOrder(TreeNode tree) {
           if (tree == null)
               return;
           Stack<TreeNode> stack = new Stack<>();
           stack.push(tree);
           TreeNode c;
           while (!stack.isEmpty()) {
               c = stack.peek();
               if (c.left != null && tree != c.left && tree != c.right) {
                    stack.push(c.left);
                } else if (c.right != null && tree != c.right) {
                    stack.push(c.right);
                } else {
                    System.out.print(stack.pop().val + " ");
                    tree = c;
                }
            }
        }

BFS广度优先遍历

他的访问顺序是:先访问上一层,在访问下一层,一层一层的往下访问

所以上图前序遍历的结果是:A→B→E→C→D→F
在这里插入图片描述

//  代码如下
        public static void levelOrder(TreeNode tree) {
          if (tree == null)
              return;
          LinkedList<TreeNode> list = new LinkedList<>();//链表,这里我们可以把它看做队列
          list.add(tree);//相当于把数据加入到队列尾部
          while (!list.isEmpty()) {
              TreeNode node = list.poll();//poll方法相当于移除队列头部的元素
              System.out.println(node.val);
              if (node.left != null)
                   list.add(node.left);
               if (node.right != null)
                   list.add(node.right);
           }
       }
   //     递归的写法

        public static void levelOrder(TreeNode tree) {
            int depth = depth(tree);
            for (int level = 0; level < depth; level++) {
                printLevel(tree, level);
            }
        }
        
        private static int depth(TreeNode tree) {
           if (tree == null)
                return 0;
            int leftDepth = depth(tree.left);
            int rightDepth = depth(tree.right);
            return Math.max(leftDepth, rightDepth) + 1;
        }
        
        
        private static void printLevel(TreeNode tree, int level) {
            if (tree == null)
                return;
            if (level == 0) {
                System.out.print(" " + tree.val);
            } else {
                printLevel(tree.left, level - 1);
                printLevel(tree.right, level - 1);
            }
        }
    //    如果想把遍历的结果存放到list中,我们还可以这样写

        public static List<List<Integer>> levelOrder(TreeNode tree) {
            if (tree == null)
                return null;
            List<List<Integer>> list = new ArrayList<>();
            bfs(tree, 0, list);
            return list;
        }

        private static void bfs(TreeNode tree, int level, List<List<Integer>> list) {
            if (tree == null)
                return;
            if (level >= list.size()) {
                List<Integer> subList = new ArrayList<>();
                subList.add(tree.val);
                list.add(subList);
            } else {
                list.get(level).add(tree.val);
            }
            bfs(tree.left, level + 1, list);
            bfs(tree.right, level + 1, list);
        }

DFS深度优先遍历

他的访问顺序是:先访根节点,然后左结点,一直往下,直到最左结点没有子节点的时候然后往上退一步到父节点,然后父节点的右子节点在重复上面步骤……

所以上图前序遍历的结果是:A→B→C→D→E→F

在这里插入图片描述


  //    代码如下
      public static void treeDFS(TreeNode root) {
          Stack<TreeNode> stack = new Stack<>();
          stack.add(root);
          while (!stack.empty()) {
              TreeNode node = stack.pop();
              System.out.println(node.val);
              if (node.right != null) {
                  stack.push(node.right);
              }
               if (node.left != null) {
                   stack.push(node.left);
               }
           }
       }
       // 递归的写法

        public static void treeDFS(TreeNode root) {
            if (root == null)
                return;
            System.out.println(root.val);
            treeDFS(root.left);
            treeDFS(root.right);
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/524083.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TS38.331中need -M/R/N/S 的含义

need M&#xff1a;这种字段需要UE在不存在时维护&#xff1b;need R&#xff1a;当RRC中此字段不存在时&#xff0c;UE需要释放&#xff1b;need N&#xff1a;当此字段不存在时&#xff0c;UE不需要采取任何行动&#xff08;即UE不需要保持该字段的任何现有值&#xff09;&am…

如何使用单片机点亮LED灯,并使用按键控制[51单片机]

首先先看一下我的板子&#xff0c;如果我们板子不相同&#xff0c;可能操作也不太相同 我们就不讲底层原理了&#xff0c;直接看&#xff0c;我们可以看到板子上有 8个LED灯 那这个8个LED用什么来控制呢&#xff0c;我们先看底层的线路图&#xff0c;所有的LEDD都连接到了P2带后…

云原生技术中的容器技术有哪些?

文章目录 云原生技术中的容器技术有哪些1、云原生的含义2、容器的含义3、云原生的技术的基石&#xff1a;容器技术4、容器技术有哪些? 结语 云原生技术中的容器技术有哪些 在现今的安全行业中云原生安全技术中的容器安全技术有哪些呢&#xff0c;很多用户都不知道具体的含义以…

Linux程序设计之UDP通信

1.UDP通信是不可靠的、无连接的通信&#xff0c;客户端只需要服务器端的地址信息即可与之进行通信。UDP通信的基本流程如下&#xff1a; 2.利用UDP实现服务器端与客户端的通信如下&#xff1a; /*UDP通信*/ //服务端#include <stdio.h> #include <string.h> #incl…

低造价形状记忆合金相变温度DSC热分析替代技术:帕尔贴热电装置和电阻温度测量

摘要&#xff1a;形状记忆合金&#xff08;SMA&#xff09;是一种先进的金属材料&#xff0c;其物理和机械性能本质上依赖于温度。为了快速和低成本的实现SMA相变温度和热滞后性能的测试表征&#xff0c;基于更灵敏的电阻温度依赖关系&#xff0c;本文提出了采用帕尔贴TEC加热制…

论文学习笔记:ViT Vision Transformer An Image is worth 16X16 words

论文阅读&#xff1a;ViT Vision Transformer An Image is worth 16X16 words 今天介绍的是 Transformer 在视觉领域的一篇非常重要的论文&#xff0c;Vision Transformer&#xff0c;这篇文章发表在 2021 ICLR 的会议上。长久以来 CNN 一直是 CV 领域最主流的模型&#xff0c…

从零开始:开发一款应用程序的完整流程技巧

在数字化快速发展的现在&#xff0c;开发一款应用程序已经不是一件困难的事情。低代码应用开发平台的诞生更是让应用开发变成一项人人都能快速掌握的技能。之前&#xff0c;我们使用Java、C语言等传统的语言技术进行应用开发&#xff0c;来满足企业的业务应用需求。但是&#x…

rm / -rf指令的作用是?

学习Linux 指令&#xff0c;它是操作系统的前端&#xff0c;学好这部分内容一方面可以帮助你应对工作场景&#xff0c;另一方面可以让你在学习操作系统底层知识前&#xff0c;对 Linux 有一个大概的了解。 学习 Linux 指令之前&#xff0c;先来说一下什么是 Shell&#xff1f;S…

使用FFMPEG加载外挂字幕小记

ffmpeg版本&#xff1a; FFMEPEG 4.4 继上一篇简易播放器实现后&#xff0c;优化过程中&#xff0c;加载外挂字幕小记的过程和遇到的坑记录如下&#xff1a; 视频字幕分为三种。 内嵌字幕&#xff0c;字幕与视频图像合二为一&#xff0c;成为视频帧的一部分。 内封字幕&…

Python浪漫520表白代码

目录 前言 表白界面 跳动的爱心 漂浮的爱心 满屏表白代码 前言 520是每年的5月20日&#xff0c;因数字“520”与“我爱你”发音相似而被许多年轻人用作表达爱意的节日。这个节日起源于中国互联网文化&#xff0c;逐渐传递到其他国家和地区。在这一天&#xff0c;情侣们通…

C++:深入理解C++11新特性:Chapter3:左值和右值

Chapter3&#xff1a;左值和右值 1. 将右值绑定到 左值2. 将右值绑定到 常量左值引用3. 将右值绑定到右值引用总结&#xff1a;5. 左值&#xff0c;右值和右值引用6. 引用类型可以引用的值 在C语言中&#xff0c;我们常常会提起左值&#xff08;lvalue&#xff09;,右值&#x…

数组--part 5--螺旋矩阵(力扣59/54)(剑指offer 29)

文章目录 基本算法思想leetcode 59 螺旋矩阵 IIleetcode 54 螺旋矩阵剑指Offer 29 顺时针打印矩阵 基本算法思想 建议先去把题目看了&#xff0c;再来思考相关的代码。 错误的想法&#xff1a;实际上这种题型并不存在算法&#xff0c;只涉及到模拟&#xff0c;但是模拟难度并…

【51单片机】外部中断

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Love Story】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;原理 &#x1f354;注意管…

未来的数字签名方案:Dilithium、FALCON 和 SPHINCS+

1. 引言 当前的数字签名方案主要有&#xff1a; RSAECDSAEdDSA&#xff1a;已废弃DSA&#xff0c;将EdDSA纳入FIPS 186。 这些数字签名方案都不可抗量子攻击。为此&#xff0c;需要新的量子强健的签名方案&#xff0c;NIST引入了3种新的PQC数字签名标准化方案&#xff1a; …

软考A计划-真题-分类精讲汇总-第八章(面向对象)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

【CSS基础】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、CSS是什么&#xff1f; 语法规范 引入方…

基于matlab使用主动声纳系统进行水下目标检测

一、前言 此示例演示如何模拟具有两个目标的主动单基地声纳方案。声纳系统由各向同性投影仪阵列和单个水听器元件组成。投影仪阵列呈球形。反向散射信号由水听器接收。接收到的信号包括直接和多路径贡献。 二、水下环境 在浅水环境中&#xff0c;声源和目标之间存在多个传播路径…

网络工程师常用命令排行榜,Ping就在这一行

大家好&#xff0c;我是老杨。 如果问你&#xff0c;你在日常工作中用的最频繁的命令是哪个&#xff0c;你下意识的第一反应是什么。 年前&#xff0c;我做了个不完全统计&#xff0c;大概有100多位粉丝参与的问卷调查&#xff0c; 调查每一位网工在解决网络故障时使用最多的…

[PCIE703]FPGA实时处理器-XCKU060+ARM(华为海思视频处理器-HI3531DV200)高性能综合视频图像处理平台设计资料及原理图分享

板卡概述 PCIE703是自主研制的一款基于PCIE总线架构的高性能综合视频图像处理平台&#xff0c;该平台采用Xilinx的高性能Kintex UltraScale系列FPGA加上华为海思的高性能视频处理器来实现。 华为海思的HI3531DV200是一款集成了ARM A53四核处理器性能强大的神经网络引擎&#x…

基于matlab编程的线性规划整数解问题求解

背景&#xff1a; 自己读研期间曾经用matlab做过一些小项目和实验&#xff0c;自己的毕业论文实验仿真也是用的matlab&#xff0c;最近打算更换电脑&#xff0c;在翻阅电脑磁盘的时候找到了一些和matlab相关的代码和文档&#xff0c;简单整理和分享一下。 说明&#xff1a; …