数据结构与算法学习记录--二叉树的创建,递归遍历,非递归遍历的实现
2017-09-01 11:13
706 查看
package test; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Stack; public class BinaryTree { /** * 用内部类申明结点结构 * */ class Node{ int value = 0; Node lchild = null; Node rchild = null; Node(int value){ this.value = value; } } /** * 先序创建二叉树 * i为数组下标 */ static int i = 0; Node createTree(int[] input) { Node node= null; if(input[i]<0) return node; node = new Node(input[i]); i++; node.lchild = createTree( input); i++; node.rchild = createTree(input); return node; } /** * 递归方式实现先序遍历 * @param root * @param result */ void preOrder(Node root,ArrayList<Node> result){ if(root == null) return ; result.add(root); preOrder(root.lchild,result); preOrder(root.rchild,result); } /** * 递归方式实现中序遍历 * @param root * @param result */ void midOrder(Node root,ArrayList<Node> result) { if(root == null) return ; midOrder(root.lchild, result); result.add(root); midOrder(root.rchild, result); } /** * 递归方式实现后序遍历 * @param root * @param result */ void postOrder(Node root,ArrayList<Node> result) { if(root == null) return ; postOrder(root.lchild,result); postOrder(root.rchild,result); result.add(root); } /** * 迭代方式实现先序遍历。 * 因为递归就是用到栈的原理,所以所有递归式子都可以用栈来表示,遍历一定用到了栈。 * 1.根入栈 * 2.栈顶元素出栈,右结点入栈,左节点入栈。循环该步骤 * @param root * @return */ ArrayList<Node> preOrder(Node root) { Stack<Node> stack = new Stack<Node>(); ArrayList<Node> list = new ArrayList<Node>(); if(root == null) { return list; } stack.push(root); while(!stack.isEmpty()) { Node node = stack.pop(); list.add(node); if(node.rchild!= null) stack.push(node.rchild); if(node.lchild!=null) stack.push(node.lchild); } return list; } /** * 迭代方式实现中序遍历。 * 先将所有左节点压栈,左节点为空时,说明已经到了该树枝的尽头,则栈顶元素出栈,再去遍历该结点的右子树 * @param root * @return */ ArrayList<Node> midOrder(Node root){ ArrayList<Node> list = new ArrayList<Node>(); Stack<Node> stack = new Stack<Node>(); Node node = root; if(root == null) return list; while(!stack.isEmpty() || node!=null) { while(node!=null) { stack.push(node); node = node.lchild; } node = stack.pop(); list.add(node); node = node.rchild; } return list; } /** * 迭代实现后序遍历 * 两个重要的变量:刚刚打印完的结点print和栈顶结点top(即将要打印的结点),初始值print为根节点,top为null * 1.先判断栈顶结点的左子树是否被遍历,遍历原理是:判断print是否为栈顶节点的左孩子或者右孩子结点 * 2.再判断栈顶结点的右子树是否被遍历,遍历原理是:判断print是否为栈顶节点的右孩子结点 * 3.若左右子树都被遍历了,则栈顶结点出栈,打印该该节点。 * 找到top和print结点的关系 * @param root * @return */ /***以下是自己第一次根据该思路写的代码,繁琐,理解较简单***/ public ArrayList<Node> postOrder(Node root){ Stack<Node> stack = new Stack<>(); ArrayList<Node> list = new ArrayList<>(); Node print = root; Node top = null; stack.push(root); while(!stack.isEmpty()) { top = stack.peek(); if(print == top.lchild || print == top.rchild) { // 若是左子树 if(print == top.lchild) { print = top.rchild; if(top.rchild!=null) stack.push(print); // 若是右子树 }else { list.add(top); print = top; stack.pop(); } // 若都不是,则要去遍历左右子树 }else { if(top.rchild!=null) { stack.push(top.rchild); print = top.rchild; } if(top.lchild!=null) { stack.push(top.lchild); print = top.lchild; } if(top.rchild == null && top.lchild == null) { list.add(top); print = top; stack.pop(); } } } return list; } 注:最开始写的以下部分是错的.我认为当top结点没有左右子树时,即左右子树都为null时,此时可以令刚打印结点print为右子树结点,但是此时左右子树都为null,所以print的指向的混乱的,并且也没有体现print为刚打印的结点。所以对于自己定义的结点,应该清晰的知道它的作用,并发挥出其作用,不可胡乱使用,造成变量使用混乱。 if(top.rchild == null && top.lchild == null) print = top.rchild; /**以下是参考给出的代码,非常简化***/ ArrayList<Node> postOrder(Node root){ ArrayList<Node> list = new ArrayList<>(); Stack<Node> stack = new Stack<>(); Node top = null; Node print = root; stack.push(root); while(!stack.isEmpty()) { //先获取栈顶元素,为了判断栈顶元素是否可以被打印,要执行后面的判断语句 top = stack.peek(); //判断栈顶元素的左子树是否被打印了 if(top.lchild!= null && top.lchild != print && top.rchild !=print) { stack.push(top.lchild); top = stack.peek(); } //判断栈顶元素的右子树是否被打印了 else if(top.rchild!=null && top.rchild!= print) { stack.push(top.rchild); top = stack.peek(); } //左子树右子树都被打印了,则打印栈顶元素 else { print = stack.pop(); list.add(print); } } return list; } /* 以上两种方法的区别在于对判断当前结点的左右子树是否为打印结点。第一种繁琐的方法是判断当为打印结点时,进行操作,需要考虑各种情况下的操作方法;第二种简单的方法是判断不为打印结点时,进行操作,只有一种操作方法。两种方法是相反的。需要多思考选择最简单的方法。 */ public static void main(String[] args) { BinaryTree bt = new BinaryTree(); //测试数据 int[] array = {3,5,-1,9,-1,-1,7,11,-1,-1,13,-1,-1}; Node root =bt.createTree(array); ArrayList<Node> list = bt.postOrder(root); for(Node node : list) { System.out.print(node.value + " "); } } }
相关文章推荐
- java实现二叉树的创建及三种递归遍历
- 递归方法实现二叉树的创建,遍历
- 大话数据结构(七)——二叉树创建与遍历(递归、非递归)的java实现
- 不疯魔,不成活!——二叉树的创建、遍历(递归实现)等操作。
- 用c语言创建一颗二叉树,用递归方法实现对其进行先序、中序和后序遍历的操作。
- 二叉树的创建(先序创建的)及先序遍历 中序遍历 后序遍历的递归和非递归实现
- 二叉树创建、遍历的递归和非递归实现
- 采用二叉链表结构实现二叉树,并以递归遍历思想实现二叉树的创建、二叉树的遍历(先序、中序、后序和层次遍历)
- 二叉树的创建、前序中序后序递归遍历与非递归遍历、层序遍历以及二叉树简单应用的C语言实现
- c++实现二叉树的非递归创建以及非递归先序、中序、后序遍历
- 二叉树的创建,先序、中序、后序遍历的递归实现以及层序遍历
- 数据结构与算法分析学习笔记--第四章(二叉树:创建、递归遍历、非递归遍历、根据数据删除结点等)
- 【python中二叉树的实现】python中二叉树的创建、三种方式递归遍历和非递归遍历
- javascript实现二叉树的创建,遍历,添加,查找最大值最小值和指定值的寻找及删除功能——递归的多次运用
- Java创建二叉树及其遍历的递归和非递归实现
- 二叉树的创建遍历 递归实现
- 二叉树的简单递归实现(创建,遍历,高度,大小)
- 二叉树的创建与先、中、后序遍历递归实现
- ::递归实现——创建二叉树 ----> 装入数据--->遍历---> 显示 --->销毁
- C++实现二叉树所有操作 -- 创建递归遍历迭代遍历拷贝清空查找