摘要:之前在网上翻过很多其他人写好的算法,很好,但是他们写的算法已经是优化过,或者,经过修剪的,算法这个东西,是个循序渐进的过程,先实现,然后优化,自己写这些,只是为了记录学习经历,如若对您有启发,那再好不过。
- 二叉树简介
对于二叉树的介绍,不做赘述,只需知道他的结构即可,由根节点,左右子树构成。 遍历
递归遍历,不赘述,很简单的代码,这里只说非递归形式,非递归就要借助一种数据结构,栈,其实在递归里,函数的递归调用也是通过栈的方式,保存了之前函数运行的环境,以便递归调用回归的时候,恢复当时的运行环境,不过是代码运行平台帮我们在后台进行的;- 前序遍历
遵循“根–> 左–> 右”的顺序,根据栈的 “先进后出” 的特点,所以数据进栈的顺序,应该是:“右–>左–>根” 的顺序,因为我们首先要访问根节点,根据“先进后出”,他应该是最后一个入栈;代码如下:
//node 类 static class Node{ int val; Node left; Node right; public Node(int val) { this.val = val; this.left=null; this.right=null; } }
//前序遍历 static void pre(Node root) { Stack<Node> stack = new Stack<>(); stack.push(root); while(!stack.isEmpty()) { Node cur = stack.pop(); if(!visited.contains(cur)) { System.out.println(cur.val); visited.add(cur); } //按照 右 左 根 的顺序入栈 if(cur.right != null) stack.push(cur.right); if(cur.left != null) stack.push(cur.left); if(!visited.contains(cur)) stack.push(cur); } }
中序遍历
和前序一样的思想,中序访问的顺序是“左中右”,所以数据入栈的顺序是:“右中左”,只不过是节点访问的时候,判断条件需要调整一下;static void mid(Node root) { Stack<Node> stack = new Stack<>(); stack.push(root); while(!stack.isEmpty()) { Node cur = stack.pop(); if(!visited.contains(cur) && (cur.left==null || visited.contains(cur.left))) { System.out.println(cur.val); visited.add(cur); } if(cur.right != null) stack.push(cur.right); if(!visited.contains(cur)) stack.push(cur); if(cur.left != null) stack.push(cur.left); } }
后序遍历
一样的思想,后序遍历的访问顺序是 “左右中”,所以数据入栈的顺序为:“中右左”,访问节点的判断条件要修改一下static void after(Node root) { Stack<Node> stack = new Stack<>(); stack.push(root); while(!stack.isEmpty()) { Node cur = stack.pop(); if(!visited.contains(cur) && ((cur.left==null && cur.right==null) || visited.contains(cur.left) || visited.contains(cur.right) )) { System.out.println(cur.val); visited.add(cur); } if(!visited.contains(cur)) stack.push(cur); if(cur.right != null) stack.push(cur.right); if(cur.left != null) stack.push(cur.left); } }
- 前序遍历
说明:这个过程是我自己想的,肯定还是需要优化,但是便于理解,先记录一下,后面再进行优化。