【算法】通过递归和非递归实现树的前中后序以及广度优先搜索和深度优先搜索

简介: 【算法】通过递归和非递归实现树的前中后序以及广度优先搜索和深度优先搜索

基本概念

树是一个有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);
        }


目录
打赏
0
1
0
0
5
分享
相关文章
基于 PHP 语言深度优先搜索算法的局域网网络监控软件研究
在当下数字化时代,局域网作为企业与机构内部信息交互的核心载体,其稳定性与安全性备受关注。局域网网络监控软件随之兴起,成为保障网络正常运转的关键工具。此类软件的高效运行依托于多种数据结构与算法,本文将聚焦深度优先搜索(DFS)算法,探究其在局域网网络监控软件中的应用,并借助 PHP 语言代码示例予以详细阐释。
22 1
内网网管软件中基于 Node.js 的深度优先搜索算法剖析
内网网管软件在企业网络中不可或缺,涵盖设备管理、流量监控和安全防护。本文基于Node.js实现深度优先搜索(DFS)算法,解析其在网络拓扑遍历中的应用。通过DFS,可高效获取内网设备连接关系,助力故障排查与网络规划。代码示例展示了图结构的构建及DFS的具体实现,为内网管理提供技术支持。
47 11
算法系列之搜索算法-深度优先搜索DFS
深度优先搜索和广度优先搜索一样,都是对图进行搜索的算法,目的也都是从起点开始搜索,直到到达顶点。深度优先搜索会沿着一条路径不断的往下搜索,直到不能够在继续为止,然后在折返,开始搜索下一条候补路径。
105 62
算法系列之搜索算法-深度优先搜索DFS
|
17天前
|
算法系列之深度优先搜索寻找妖怪和尚过河问题的所有方式
在算法学习中,深度优先搜索(DFS)是一种常用的图搜索算法,通过递归或栈实现,适合路径搜索、连通性、拓扑排序、回溯、生成、环路检测、强连通分量和可达性等问题。本文将介绍如何利用深度优先搜索解决“妖怪和尚过河问题”的所有方式。
65 26
算法系列之深度优先搜索寻找妖怪和尚过河问题的所有方式
|
18天前
|
算法系列之广度优先搜索解决妖怪和尚过河问题
BFS 是一种逐层扩展的搜索算法,适用于寻找最短路径。我们可以将每个状态看作图中的一个节点,合法的移动就是节点之间的边。通过 BFS,我们可以找到从初始状态到目标状态的最短路径。
86 30
算法系列之广度优先搜索解决妖怪和尚过河问题
|
16天前
|
算法系列之深度/广度优先搜索解决水桶分水的最优解及全部解
在算法学习中,广度优先搜索(BFS)适用于解决最短路径问题、状态转换问题等。深度优先搜索(DFS)适合路径搜索等问题。本文将介绍如何利用广度优先搜索解决寻找`3 个 3、5、8 升水桶均分 8 升水`的最优解及深度优先搜索寻找可以解决此问题的所有解决方案。
55 7
 算法系列之深度/广度优先搜索解决水桶分水的最优解及全部解
|
21天前
|
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
40 3
 算法系列之数据结构-Huffman树
基于 Node.js 深度优先搜索算法的上网监管软件研究
在数字化时代,网络环境呈现出高度的复杂性与动态性,上网监管软件在维护网络秩序与安全方面的重要性与日俱增。此类软件依托各类数据结构与算法,实现对网络活动的精准监测与高效管理。本文将深度聚焦于深度优先搜索(DFS)算法,并结合 Node.js 编程语言,深入剖析其在上网监管软件中的应用机制与效能。
24 6
|
1月前
|
算法系列之递归反转单链表
递归反转链表的基本思路是将当前节点的next指针指向前一个节点,然后递归地对下一个节点进行同样的操作。递归的核心思想是将问题分解为更小的子问题,直到达到基本情况(通常是链表末尾)。
41 5
算法系列之递归反转单链表
|
21天前
|
公司电脑网络监控场景下 Python 广度优先搜索算法的深度剖析
在数字化办公时代,公司电脑网络监控至关重要。广度优先搜索(BFS)算法在构建网络拓扑、检测安全威胁和优化资源分配方面发挥重要作用。通过Python代码示例展示其应用流程,助力企业提升网络安全与效率。未来,更多创新算法将融入该领域,保障企业数字化发展。
41 10

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等