数据结构与算法---树---前、中、后、层序遍历二叉树

144. 二叉树的前序遍历

在这里插入图片描述


抛开这道题,如果只是简单的打印二树的前序遍历节点值还是很简单的。
但,如果加上将值放入数组再返回,还是有难度的。

我们从简到难
对于前序、中序、后序遍历,最简单的莫过于递归

前序、中序、后序遍历(递归)

public class Source {
	
	public static void main(String[] args)
	{
		//构建一棵树
		TreeNode a = new TreeNode(1);
        TreeNode b = new TreeNode(2);
        TreeNode c = new TreeNode(3);
        TreeNode d = new TreeNode(4);
        TreeNode e = new TreeNode(5);
        TreeNode f = new TreeNode(6);
        TreeNode g = new TreeNode(7);
        a.left = b;
        a.right = c;
        b.right = d;
        c.left = e;
        c.right = f;
        f.left = g;
        
        /**
         * 				1
         * 			2       3
         * 			  4   5   6
         *                   7
         * */
		
		preorder(a);
        System.out.println();
        inorder(a);
        System.out.println();
        postorder(a);
	}
	
	/**前序遍历*/
	public static void preorder(TreeNode root) {
        if(root == null) return;
        System.out.print(root.val + " ");
        preorder(root.left);
        preorder(root.right);
    }
	
	/**中序遍历*/
	public static void inorder(TreeNode root) {
        if(root == null) return;
        inorder(root.left);
        System.out.print(root.val + " ");
        inorder(root.right);
    }
	
	/**后序遍历*/
	public static void postorder(TreeNode root) {
        if(root == null) return;
        postorder(root.left);
        postorder(root.right);
        System.out.print(root.val + " ");
    }

}


class TreeNode{
	int val;
	TreeNode left;
	TreeNode right;
	TreeNode(int x) { 
		val = x;
	}
}

二叉树的前序遍历,中序遍历,后序遍历(Java实现)

写完了递归的前序、中序、后序遍历,我们来学习一下层序遍历

层序遍历

思路:

层序遍历需要使用队列来解决

  1. 将根结点入队
  2. 循环以下步骤,直到队列为空
    出队第一个元素,并打印节点的值
    出队节点的左子节点不为空,将出队节点的左子节点入队
    出队节点的右子节点不为空,将出队节点的右子节点入队
/**层序遍历*/
	public static void levelorder(TreeNode root) {
        if(root == null) return;
        //创建一个队列
        Queue <TreeNode> queue = new LinkedList<TreeNode>();
        //入队
        queue.add(root);
        //循环
        while(!queue.isEmpty())
        {
        	TreeNode node = queue.poll();
    		System.out.print(node.val + " ");
        	if (node.left != null) {
            	queue.add(node.left);
			}
        	
        	if (node.right != null) {
            	queue.add(node.right);
			}
        }
    }

写完了简单的递归,我们学习下非递归方法(迭代方法)

前序、中序、后序遍历(非递归)

中序遍历(非递归)

浙江大学老师的中序遍历:
思路:
  1. 遇到一个结点,就把它压栈,并去遍历它的左子树
  2. 当左子树遍历结束后,从栈顶弹出这个结点并访问它
  3. 然后按其右指针再去中序遍历该结点的右子树
/**中序遍历(非递归)*/
	public static void inorder2(TreeNode root)
	{
		if(root == null) return;
		TreeNode node = root;
		
		//创建一个栈
		Stack <TreeNode> stack = new Stack<TreeNode>();
		
		while (node != null || !stack.isEmpty()) {
			while (node != null) {
				stack.push(node);
				node = node.left;
			}
			if (!stack.isEmpty()) {
				node = stack.pop();
				System.out.print(node.val + " ");
				node = node.right;
			}
		}
	}
MJ大神的中序遍历:
思路:

利用栈来实现
1 设置node = root;
2 循环执行以下操作:
如果node != null
则,将node入栈,并且设置node = node.left
如果node == null,则判断stack是否为空
如果stack为空,则结束遍历。
如果stack不为空,则弹出栈顶元素并赋值给node,访问node,再将node = node.right;

/**中序遍历(非递归)*/
	public static void inorder3(TreeNode root)
	{
		if(root == null) return;
		TreeNode node = root;
		
		//创建一个栈
		Stack <TreeNode> stack = new Stack<TreeNode>();
		
		while(true)
		{
			if (node != null) {
				stack.push(node);
				node = node.left;
			}else if (!stack.isEmpty()) {
				node = stack.pop();
				System.out.print(node.val + " ");
				node = node.right;
			}else {
				return;
			}
		}
	}

两者看着有语法上的区别,但思路是一样的,都是直接将node的左子树入栈,然后出栈顶结点,并打印出栈结点,然后遍历出栈结点的右结点。

根据以上思路,不难想出前序遍历

前序遍历

/**前序遍历(非递归)*/
	public static void preorder3(TreeNode root)
	{
		if(root == null) return;
		TreeNode node = root;
		
		//创建一个栈
		Stack <TreeNode> stack = new Stack<TreeNode>();
		
		while(true)
		{
			if (node != null) {
				System.out.print(node.val + " ");
				stack.push(node);
				node = node.left;
			}else if (!stack.isEmpty()) {
				node = stack.pop();
				node = node.right;
			}else {
				return;
			}
		}
	}

前序遍历,利用栈的另一种写法:剑指 Offer 27. 二叉树的镜像

后序遍历

后序遍历稍微不一样,但还是借助栈来实现的

在这里插入图片描述
从上图可以看出,树的后序遍历是1 3 2 5 4 7 6的顺序
但是,开始位置永远是6
那么,可以将6入栈,然后将6的右子结点7入栈,然后再将6的左子结点4入栈,重复以上操作。这样,在出栈的时候,就是后序遍历顺序。

/**后序遍历(非递归)*/
	public static void postorder3(TreeNode root)
	{
		if(root == null) return;
		TreeNode node = root;
		
		TreeNode preNode = null;//记录上一次弹出访问的结点 
		//创建一个栈
		Stack <TreeNode> stack = new Stack<TreeNode>();
		stack.push(node);
		while(!stack.isEmpty())
		{
			TreeNode topNode = stack.peek();//偷偷看一眼栈顶元素是谁,不需要出栈
			if((topNode.right == null && topNode.left == null) || (preNode != null && preNode.parent == top))//叶子结点
			{
				preNode = stack.pop();
				System.out.print(preNode.val + " ");
			}else{
				if(topNode.right != null)
				{
					stack.push(topNode.right);
				}
			
				if(topNode.left != null)
				{
					stack.push(topNode.left);
				}
			}
		}
	}

递归解决144的问题

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> listArray = new ArrayList();
        preorder(root, listArray);
        return listArray;
    }

    private void preorder(TreeNode root, List<Integer> listArray) {
        if(root == null) return;
        listArray.add(root.val);
        preorder(root.left, listArray);
        preorder(root.right, listArray);
    }
}

非递归解决144的问题

暂无

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值