二叉树的前序,中序,后序遍历(递归非递归实现)

给定如图二叉树,请用递归和非递归的方式实现前序,中序,后序遍历


1.前序遍历

1.1 递归方式

递归方式十分简单,因为是前序遍历,所以在递归调用前先打印当前节点的值,然后分别将左孩子和右孩子作为参数传入递归函数

public void preTraversal1(TreeNode root){
		if(root == null) return;  //判空
		System.out.println("print:"+root.val);
		preTraversal1(root.left);
		preTraversal1(root.right);
	}
注:TreeNode的代码文末给出

1.2 非递归实现(使用一个栈)

一、我们定义一个栈stack,然后将root节点存入栈中(push操作)

二、只要当前栈中元素不为空,那么栈顶元素出栈(pop操作)并打印,如果出栈元素存在右孩子或左孩子(注意顺序),则将右孩子或左孩子加入栈中(push操作)

三、重复上述第二步操作

下面我们看图说话,

简单说下过程,

首先,push root元素到栈中,然后弹出root,并按顺序加入右孩子(3),左孩子(2)

然后,弹出栈顶元素(2),检查是否存在右孩子(5),左孩子(4),如果存在,则按顺序push进栈中

再次之,弹出栈顶元素(4),检查无孩子,继续弹出栈顶元素(5),检查无孩子,继续弹出栈顶元素(3),加入右孩子(7),加入左孩子(6)

最后,依次弹出无孩子的栈顶元素(6,7)

下面看代码实现

public void preTraversal2(TreeNode root){
		if(root==null) return;
		Deque<TreeNode> stack = new LinkedList<TreeNode>();
		stack.push(root);
		while(stack.size()!=0){
			TreeNode temp = stack.pop();
			System.out.println("print:"+temp.val);
			if(temp.right!=null) stack.push(temp.right);
			if(temp.left!=null) stack.push(temp.left);
		}
	}

注:Deque为双端队列,这里用作栈


2.中序遍历

2.1 递归方式

有了之前的理解,这里直接贴出代码

public void inTraversal(TreeNode root){
		if(root == null) return;
		inTraversal(root.left);
		System.out.println("print:"+root.val);
		inTraversal(root.right);
	}
2.2 非递归方式(一个栈实现)

一、我们定义一个栈stack,并将根节点root push进栈,定义一个current变量,开始时指向root节点

二、先把current节点压入栈中,然后将整棵树的左边界压入栈中(相对current节点而言),即不断令current=current.left,重复此步骤

三、重复第二步,当遇到current左节点为空时,弹出栈顶元素记为node,并令current=node.right,然后继续步骤二

四、直到stack为空时,结束整个过程

下面看图说话:


简单分析

首先,从root插入左边界得栈【1,2,4】,栈顶元素(4)已经无左边界,current变为null,出栈,而且无右孩子,current继续为null

然后,因为current继续为null,所以栈顶元素(2)弹出,右孩子(5)加入栈顶,但右孩子(5),左右边界均无,弹出,current继续为null

再次之,因为current继续为null,所以栈顶元素(1)弹出,右孩子(3)加入栈顶,左孩子(6)加入栈顶,而左孩子(6)无左右边界,弹出,current继续为null

最后,因为current继续为null,所以栈顶元素(3)弹出,右孩子(7)加入栈顶,而右孩子(7)无左右边界,继续弹出,此时栈为空,终止。

下面贴出代码:

public void inTraversal1(TreeNode root){
		if(root==null) return;
		Deque<TreeNode> stack = new LinkedList<TreeNode>();
		TreeNode current = root;
		stack.push(root);
		while(stack.size()!=0){
			if(current==null){
				TreeNode temp = stack.pop();
				System.out.println("print:"+temp.val);
				if(temp.right!=null){
					 current = temp.right;
					 stack.push(current);
				}
			}else{
				current = current.left;
				if(current!=null) stack.push(current);
			}
		}
	}

3. 后序遍历

3.1 递归方式

直接给出代码

public void postTraversal(TreeNode root){
		if(root == null) return;
		postTraversal(root.left);
		postTraversal(root.right);
		System.out.println("print:"+root.val);
	}

3.2 非递归方式(两个栈)

一.声明一个栈stack1,并将根节点压入栈中

二.从stack1中弹出的节点记为current,并将current的左孩子和右孩子压入stack1

三.在整个过程中,从stack1弹出的元素均放入stack2中

四.不断重复二,三步骤,直到stack1为空为止

下面看图说话:

下面贴出代码

public void postTraversal1(TreeNode root){
		Deque<TreeNode> stack1 = new LinkedList<TreeNode>();
		Deque<TreeNode> stack2 = new LinkedList<TreeNode>();
		stack1.push(root);
		while(stack1.size()!=0){
			TreeNode current = stack1.pop();
			if(current.left!=null) stack1.push(current.left);
			if(current.right!=null) stack1.push(current.right);
			stack2.push(current);
		}
		while(stack2.size()!=0){
			System.out.println("print:"+stack2.pop().val);
		}
	}

注:在分析前两个的基础上,自行分析第三个,后序遍历还有一种只用一个栈实现的方式,有兴趣可以自己查阅。

4.TreeNode代码

	public int val = 0;
	public TreeNode left = null;
	public TreeNode right = null;
	public TreeNode(int val){
		this.val = val;
	}
	
	/**
	 * 构建一棵测试树
	 * */
	public static TreeNode getTestTree(){
		TreeNode root = new TreeNode(1);
		root.left = new TreeNode(2);
		root.right = new TreeNode(3);
		root.left.left = new TreeNode(4);
		root.left.right = new TreeNode(5);
		root.right.left = new TreeNode(6);
		root.right.right = new TreeNode(7);
		return root;
	}
}

支持原创,转载请标明出处。


猜你喜欢

转载自blog.csdn.net/VP_19951105/article/details/75000047