二叉树前序Preorder遍历和后序Postorder遍历的非递归实现

来源:互联网 发布:js单例和实际化 编辑:程序博客网 时间:2024/06/02 09:08

1简述

二叉树的前序遍历和后序遍历的递归实现是相对容易实现的,而且非常便于理解。


对于前序遍历

       首先访问当前节点;

       如果左子树非空,前序遍历左子树;

       如果右子树非空,前序遍历右子树


对于后序遍历

       如果左子树非空,后序遍历左子树;

       如果右子树非空,后序遍历右子树;

       最后访问当前节点


2非递归实战

当采用非递归方法来说实现时,就要略微复杂一些了。

       首先来看前序遍历

       根据前序遍历的定义,我们总是访问当前节点,访问左子树,访问当前节点,访问左子树。。。只有当左子树为空时才会去访问右子树,接着就是重复这一过程;而当右子树为空的时候,我们要退回到上一个节点,查看上一个节点右子树是否为空,若非空,接着重复访问过程。因为有一个后退的过程,所以我们考虑用栈来保存访问经过的节点。在每次循环过程中,我们总会先判断左子树是否已经被访问过,所以我们需要对已经访问过的节点进行标记。对于LeetCode上的原题(网址https://oj.leetcode.com/problems/binary-tree-preorder-traversal/)来说,具体代码过程如下:

public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new LinkedList<Integer>(); // List to save the result of Binary Tree Preorder Traversalif(root == null) {return result;}Set<TreeNode> set = new HashSet<TreeNode>(); // Set to save the TreeNode that has been visited.Stack<TreeNode> stk = new Stack<TreeNode>(); // Stack to allow to step back to previous TreeNodeTreeNode currentNode;// First, visit the rootset.add(root);stk.push(root);result.add(root.val);while(!stk.isEmpty()) {currentNode = stk.peek(); // Get the top TreeNode that has been visited but not pop it.while(currentNode.left != null && !set.contains(currentNode.left)) { // Has left child but not been visited, just visit it!currentNode = currentNode.left;set.add(currentNode);stk.push(currentNode);result.add(currentNode.val);}// Visit until the left is null// Check whether has right child and if it is visitedif(currentNode.right != null && !set.contains(currentNode.right)) {currentNode = currentNode.right;set.add(currentNode);stk.push(currentNode);result.add(currentNode.val);} else { // Has no right child, just pop it outstk.pop();}}return result;}


         后序遍历也来分析一下。后序遍历需要先遍历左子树,再遍历右子树,最后才是访问当前节点,和前序遍历一样,也是需要栈的支持,保存当前节点,然后左子树非空访问左子树,左子树非空访问左子树。。。直到左子树为空,然后访问右子树;在右子树访问完了之后才访问该节点。对于LeetCode上的原题(网址https://oj.leetcode.com/problems/binary-tree-postorder-traversal/)来说,具体代码如下:

public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<Integer>();if(root == null) {return result;}Set<TreeNode> set = new HashSet<TreeNode>();Stack<TreeNode> stk = new Stack<TreeNode>();stk.push(root);TreeNode currentNode;while(!stk.isEmpty()) {currentNode = stk.peek(); // Get the top TreeNode but not pop itwhile(currentNode.left != null && !set.contains(currentNode.left)) { // Walk until left child is null, and check whether it has been visitedstk.push(currentNode.left);currentNode = currentNode.left;}if(currentNode.right != null && !set.contains(currentNode.right)) { // push the right child if it has not been visitedstk.push(currentNode.right);} else {                             // Has no right child or it has been visited before, just visit it!set.add(currentNode);result.add(currentNode.val);stk.pop();}}return result;}



0 0