龙空技术网

java使用递归和非递归方式实现二叉树的后序遍历

万物生的好物 131

前言:

今天各位老铁们对“二叉树后序遍历输出算法思路”大体比较着重,你们都想要知道一些“二叉树后序遍历输出算法思路”的相关资讯。那么小编同时在网络上搜集了一些关于“二叉树后序遍历输出算法思路””的相关知识,希望看官们能喜欢,朋友们一起来学习一下吧!

二叉树的后序遍历是比较常见的一种访问方式,它是通过左---右---根的顺序访问树的,

了解并掌握树的后序遍历是很有必要的,也是学习算法的基础,这里分别给出递归算法和非递归算法,

递归算法很简单,非递归稍微复杂,它比中序和前序更难一点,这里关系到节点重复入栈,

理解非递归的重要的一点就是:永远从最左开始遍历,如果存在右节点,此时要判断右节点是继续入栈还是略过,

这里通过visitor来标记右节点是否已经入过栈,如果入过,标记为1,下一次判断时不再入栈,直接输出当前节点即可。这里使用了标记的方式来避免重复入栈,但我想应该可以无需借助标记方式,这个应该更复杂,朋友们如果有更好的非递归算法可以在评论区分享出来哦

以下下图为例,输出后序遍历

预期的结果为: 4, 8, 6, 12, 16, 14, 10

递归和非递归代码如下:

import java.util.ArrayList;import java.util.List;import java.util.Stack;/** * 后序遍历的非递归和递归的实现 *  * @author ssj * */public class AfterList {	public static void main(String[] args) {		// 创建一颗二叉树		TreeNode root = new TreeNode("10");		TreeNode n6 = new TreeNode("6");		TreeNode n14 = new TreeNode("14");		n6.setParent(root);		n14.setParent(root);		root.setLeft(n6);		root.setRight(n14);		TreeNode n4 = new TreeNode("4");		TreeNode n8 = new TreeNode("8");		n6.setLeft(n4);		n6.setRight(n8);		TreeNode n12 = new TreeNode("12");		TreeNode n16 = new TreeNode("16");		n14.setLeft(n12);		n14.setRight(n16);		System.out.println("---------递归遍历结果--------------------");		List list = new ArrayList();		afterListDiGui(root, list);		System.out.println(list);						System.out.println("---------非递归遍历结果--------------------");		List list2 = afterList(root);		System.out.println(list2);	}	/**	 * 递归后序遍历	 * 	 * @param root	 * @return	 */	public static void afterListDiGui(TreeNode root, List list) {		if (root == null) {			return;		}		afterListDiGui(root.left, list);		afterListDiGui(root.right, list);		list.add(root.name);	}	/**	 * 非递归后序遍历	 * 	 * @param root	 * @return	 */	public static List afterList(TreeNode root) {		Stack<TreeNode> sk = new Stack<TreeNode>();		List list = new ArrayList();		TreeNode n = root;		while (n != null) {			// 从当前节点开始,一直往左方向前进			while (n != null) {				sk.push(n);								n = n.left;			}			// 取出入栈的右节点			while (!sk.empty()) {				TreeNode n2 = sk.pop();												if (n2.right == null||n2.right.visitor) {					//不存在右节点或者右节点已经访问过了,则右节点无需再关心					list.add(n2.getName());					n2.visitor=true;				}else {					//存在右孩子未被访问,当前节点退回到栈中,先处理右孩子相关的节点					sk.push(n2);					n=n2.right;//继续上面的轮回					break;				}							}		}		return list;	}}/** * 树节点 * @author ssj * */class TreeNode {	public String name;	public TreeNode left;	public TreeNode right;	public TreeNode parent = null;	public boolean visitor=false;//标记该节点是否访问过	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public TreeNode getParent() {		return parent;	}	public void setParent(TreeNode parent) {		this.parent = parent;	}	public TreeNode(String name) {		super();		this.name = name;	}	public TreeNode getLeft() {		return left;	}	public void setLeft(TreeNode left) {		this.left = left;	}	public TreeNode getRight() {		return right;	}	public void setRight(TreeNode right) {		this.right = right;	}}

运行结果:

标签: #二叉树后序遍历输出算法思路