抛开这道题,如果只是简单的打印二树的前序遍历节点值还是很简单的。
但,如果加上将值放入数组再返回,还是有难度的。
我们从简到难
对于前序、中序、后序遍历,最简单的莫过于递归
前序、中序、后序遍历(递归)
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;
}
}
写完了递归的前序、中序、后序遍历,我们来学习一下层序遍历
层序遍历
思路:
层序遍历需要使用队列来解决
- 将根结点入队
- 循环以下步骤,直到队列为空
出队第一个元素,并打印节点的值
出队节点的左子节点不为空,将出队节点的左子节点入队
出队节点的右子节点不为空,将出队节点的右子节点入队
/**层序遍历*/
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);
}
}
}
写完了简单的递归,我们学习下非递归方法(迭代方法)
前序、中序、后序遍历(非递归)
中序遍历(非递归)
浙江大学老师的中序遍历:
思路:
- 遇到一个结点,就把它压栈,并去遍历它的左子树
- 当左子树遍历结束后,从栈顶弹出这个结点并访问它
- 然后按其右指针再去中序遍历该结点的右子树
/**中序遍历(非递归)*/
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的问题
暂无