java_leetcode刷题—二叉树遍历

递归/迭代遍历二叉树

(对应leetcode94(中序)、144(前序)、145(后序))

递归解法

前序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    System.out.print(head.value + " ");
    preOrderRecur(head.left);
    preOrderRecur(head.right);
} 

在这里插入图片描述

前序遍历结果是:ABDHKECFIGJ

中序遍历

public static void preOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    preOrderRecur(head.left);
    System.out.print(head.value + " ");
    preOrderRecur(head.right);
}

中序遍历结果是:HKDBEAIFCGJ

后序遍历

public static void postOrderRecur(TreeNode head) {
    if (head == null) {
        return;
    }
    postOrderRecur(head.left);
    postOrderRecur(head.right);
    System.out.print(head.value + " ");
}

后序遍历结果是:KHDEBIFJGCA

迭代解法

迭代与递归的区别:迭代使用的是循环结构,递归使用的是选择结构。递归能使程序的结构更清晰、更简洁、更容易让人理解,从而减少读懂代码的时间。但是大量的递归调用会建立函数的副本,会消耗大量的时间和内存。迭代则不需要反复调用函数和占用额外的内存。

迭代本质上是在模拟递归。编译器实际上是用栈来实现递归。递归有前行和退回阶段,在前行阶段,函数的局部变量、参数值以及返回地址被压入栈中。在退回阶段,数据被弹出,函数恢复被调用的状态。所以迭代的解法用栈来实现。

前序遍历

前序遍历先访问根节点,然后前序遍历左子树,再前序遍历右子树。
当用栈实现时,则先打印出根节点,然后先将右子树压入栈中再将左子树压入栈中,再进行打印。
在这里插入图片描述

public static void preOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	Stack<TreeNode> stack = new Stack<>();
	stack.push(head);
	while (!stack.isEmpty()) {
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			stack.push(node.right);
		}
		if (node.left != null) {
			stack.push(node.left);
		}
	}
}

代码详解

1、根节点压入栈中

Stack<TreeNode> stack = new Stack<>();
	stack.push(head);

2、将根节点弹出并打印

while (!stack.isEmpty()) {
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");

3、分别将右节点、左节点压入栈中

if (node.right != null) {
			stack.push(node.right);
		}
		if (node.left != null) {
			stack.push(node.left);
		}
	}
}

4、以图中二叉树为例:根节点A首先打印,之后右节点C、左节点B分别压入栈中。由于栈非空,所以栈底元素B被弹出打印,所以node为节点B。接着将B节点的右孩子E、左孩子D压入栈中。栈非空,栈底元素D被弹出打印,以此类推。最终遍历结果为:ABDHKECFIGJ。

中序遍历

中序遍历实际上是从根节点开始一直寻找他的左孩子,直到某一结点没有左孩子则打印此节点,接着看此节点有没有右孩子,没有返回上一节点,有的话看他的右孩子有没有左孩子,没有的话打印右孩子,有的话继续向下寻找没有左孩子的节点。

public static void inOrderIteration(TreeNode head) {
	if (head == null) {
		return;
	}
	TreeNode cur = head;
	Stack<TreeNode> stack = new Stack<>();
	while (!stack.isEmpty() || cur != null) {
		while (cur != null) {
			stack.push(cur);
			cur = cur.left;
		}
		TreeNode node = stack.pop();
		System.out.print(node.value + " ");
		if (node.right != null) {
			cur = node.right;
		}
	}
}

代码详解

仍然以图片二叉树为例
在这里插入图片描述
首先将根节点A压入栈中,然后用while循环寻找没有左孩子的节点,途经的节点依次压入栈中,直到找到节点H,打印。因为节点H有右孩子K,因此cur非空,压入栈中。由于K节点没有左孩子,所以打印出来。此时cur为空,继续打印栈底元素,也就是节点D。以此类推。最终中序遍历结果是:HKDBEAIFCGJ。

后序遍历

后序遍历就是当节点既没有左孩子又没有右孩子时将节点打印出来,打印完的节点相当于没有了。

public static void postOrderIteration(TreeNode head) {
		if (head == null) {
			return;
		}
		Stack<TreeNode> stack1 = new Stack<>();
		Stack<TreeNode> stack2 = new Stack<>();
		stack1.push(head);
		while (!stack1.isEmpty()) {
			TreeNode node = stack1.pop();
			stack2.push(node);
			if (node.left != null) {
				stack1.push(node.left);
			}
			if (node.right != null) {
				stack1.push(node.right);
			}
		}
		while (!stack2.isEmpty()) {
			System.out.print(stack2.pop().value + " ");
		}
	}

代码详解

在这里插入图片描述
自己不太会,写罗嗦一点。
创建两个空栈,将头节点A压入栈1中,栈1非空,头节点弹出压入栈2,头节点的左孩子B非空,压入栈1。右孩子C也非空,压入栈1。此时栈1非空,弹出栈顶元素C,压入栈2。C的左右孩子都非空,所以将F、G压入栈1,弹出栈底元素G,压入栈2。G的右孩子非空,压入栈1.栈1非空,弹出栈底元素J压入栈2。J的左右孩子都为空,但是栈1非空,所以弹出栈1的栈底元素F压入栈2.以此类推。最后将栈2中的元素依次打印。后序遍历最后的结果是:KHDEBIFJGCA。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值