码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构 递归和非递归方式实现二叉树先序、中序和后序遍历

时间:2018-02-15 18:28:49      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:举例   for   否则   数据   递归   val   break   实现   info   

  二叉树的先序遍历顺序是根、左、右;中序遍历顺序是左、根、右;后序遍历顺序是左、右、根。

  递归方式实现如下:

 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

数据结构 递归和非递归方式实现二叉树先序、中序和后序遍历

标签:举例   for   否则   数据   递归   val   break   实现   info   

原文地址:https://www.cnblogs.com/WJQ2017/p/8449573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!