二叉树的先序遍历顺序是根、左、右;中序遍历顺序是左、根、右;后序遍历顺序是左、右、根。
递归方式实现如下:
1 public class TreeNode { 2 private int value; 3 private TreeNode left, right; 4 5 public TreeNode(int data) { 6 value = data; 7 } 8 9 // 递归方式实现先序遍历 10 public void preorder(TreeNode treeNode) { 11 if (treeNode == null) { 12 return; 13 } 14 15 System.out.println(treeNode.value + " "); 16 preorder(treeNode.left); 17 preorder(treeNode.right); 18 } 19 20 // 递归方式实现中序遍历 21 public void inorder(TreeNode treeNode) { 22 if (treeNode == null) { 23 return; 24 } 25 26 inorder(treeNode.left); 27 System.out.println(treeNode.value + " "); 28 inorder(treeNode.right); 29 } 30 31 // 递归方式实现后序遍历 32 public void postorder(TreeNode treeNode) { 33 if (treeNode == null) { 34 return; 35 } 36 37 postorder(treeNode.left); 38 postorder(treeNode.right); 39 System.out.println(treeNode.value + " "); 40 } 41 }
递归方式能解决的问题都能用非递归方式来解决,因为递归方式通过函数栈来保存信息,普通的栈或队列也能达到相同效果。
非递归方式实现先序遍历,步骤如下:
1 如果当前结点为空,则结束。
2 创建实现了Queue接口的LinkedList对象,引用为queue。
3 当前结点入队列。
4 队头结点出队列,打印其结点值。其左右非空孩子结点入队列。
5 重复步骤4,直到queue为空。
举例:
结点1入队列,然后出队列并打印。结点2和3入队列。队列中结点(从队头到队尾,下同):2、3。
结点2出队列并打印,结点4和5入队列。队列中结点:3、4、5。
结点3出队列并打印,结点6和7入队列。队列中结点:4、5、6、7。
结点4出队列并打印。队列中结点:5、6、7。
结点5出队列并打印。队列中结点:6、7。
结点6出队列并打印。队列中结点:7。
结点7出队列并打印。
Java代码:
1 // 非递归方式实现先序遍历 2 public void preOrder(TreeNode cur) { 3 if (cur != null) { 4 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 5 queue.add(cur); 6 7 while (!queue.isEmpty()) { 8 cur = queue.remove(); 9 System.out.println(cur.value + " "); 10 11 TreeNode left = cur.left, right = cur.right; 12 if (left != null) { 13 queue.add(left); 14 } 15 if (right != null) { 16 queue.add(right); 17 } 18 } 19 } 20 }
非递归方式实现中序遍历,步骤如下:
1 如果当前结点为空,则结束。
2 创建实现了Deque接口的LinkedList对象,引用为stack。
3 当前结点入栈,左孩子结点不断入栈,直到没有左孩子结点。
4 栈顶结点出栈,打印其结点值。如果有右孩子结点,则把它设为当前结点;否则,重复该步骤,直到有右孩子结点或者stack为空。
5 重复步骤3和4。
举例:
二叉树看上图(下同)。
结点1、2和4入栈。栈中结点(从栈顶到栈底,下同):4、2、1。
结点4和2出栈并打印,结点5入栈。栈中结点:5、1。
结点5和1出栈并打印,结点3和6入栈。栈中结点:6和3。
结点6和3出栈并打印,结点7入栈。栈中结点:7。
结点7出栈。
Java代码:
1 // 非递归方式实现中序遍历 2 public void inOrder(TreeNode cur) { 3 if (cur != null) { 4 Deque<TreeNode> stack = new LinkedList<TreeNode>(); 5 while (true) { 6 // 已保证当前结点非空 7 stack.addFirst(cur); 8 for (cur = cur.left; cur != null; cur = cur.left) { 9 stack.addFirst(cur); 10 } 11 12 while (true) { 13 // 当前结点出栈并打印 14 cur = stack.removeFirst(); 15 System.out.println(cur.value + " "); 16 17 TreeNode right = cur.right; 18 if (right != null) { 19 cur = right; 20 break; 21 } else if (stack.isEmpty()) { 22 return; 23 } 24 } 25 } 26 } 27 }
非递归方式实现中序遍历,步骤如下:
1 如果当前结点为空,则结束。
2 创建两个实现了Deque接口的LinkedList对象,引用为stack1和stack2。
3 当前结点入栈stack1,栈顶结点出栈。该结点入栈stack2,该结点的非空左右孩子结点入栈stack1。
4 重复步骤3,直到stack1为空。
5 stack2不断出栈并打印栈顶结点值,直到stack2为空。
举例:
结点1入栈stack1。
结点1出栈,入栈stack2。结点2和3入栈stack1。
结点3出栈,入栈stack2。结点6和7入栈stack1。
结点7出栈,入栈stack2。
结点6出栈,入栈stack2。
结点2出栈,入栈stack2。结点4和5入栈stack1。
结点5出栈,入栈stack2。
结点4出栈,入栈stack2。
结点4、5、2、6、7、3、1出栈并打印。
Java代码:
1 // 非递归方式实现后序遍历 2 public void postOrder(TreeNode cur) { 3 if (cur != null) { 4 Deque<TreeNode> stack1 = new LinkedList<TreeNode>(); 5 Deque<TreeNode> stack2 = new LinkedList<TreeNode>(); 6 7 stack1.addFirst(cur); 8 while (!stack1.isEmpty()) { 9 cur = stack1.removeFirst(); 10 stack2.addFirst(cur); 11 12 TreeNode left = cur.left, right = cur.right; 13 if (left != null) { 14 stack1.addFirst(left); 15 } 16 if (right != null) { 17 stack1.addFirst(right); 18 } 19 } 20 21 while (!stack2.isEmpty()) { 22 System.out.println(stack2.removeFirst().value + " "); 23 } 24 } 25 }
参考资料
《程序员代码面试指南 IT名企算法与数据结构题目最优解》P88-95
原文地址:https://www.cnblogs.com/WJQ2017/p/8449573.html