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

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

  递归方式实现如下:

 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

时间: 2024-11-19 13:24:07

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

二叉树的广度优先遍历、深度优先遍历的递归和非递归实现方式

二叉树的遍历方式: 1.深度优先:递归,非递归实现方式 1)先序遍历:先访问根节点,再依次访问左子树和右子树 2)中序遍历:先访问左子树,再访问根节点吗,最后访问右子树 3)后序遍历:先访问左子树,再访问右子树,最后访问根节点 2.广度优先     按照树的深度,一层一层的访问树的节点 1 package Solution; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 import java.util.Stack; 6

数据结构二叉树的递归与非递归遍历之 实现可编译(1)java

前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序遍历为例进行说明,中序遍历和后序遍历,以此类推! 二叉树递归与非递归遍历的区别,虽然递归遍历,跟容易读懂,代码量少,运算快,但是却容易出现溢出的问题,所以所以非递归遍历,在处理千万级的运算量时会先的很有用处. 二叉树的先序遍历:先访问根节点,再访问先后访问左右节点.如图: 二叉树的递归遍历之java

Java数据结构系列之——树(4):二叉树的中序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树的中序遍历:递归与非递归实现 * * @author wl * */ public class BiTreeInOrder { // 中序遍历的递归实现 public static void biTreeInOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreeInOrderByRecursi

Java数据结构系列之——树(5):二叉树的后序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树后序遍历的递归与非递归实现 * * @author wl * */ public class BitreePostOrder { // 后序遍历的递归实现 public static void biTreePostOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreePostOrderByRe

二叉树的前序、中序、后序遍历(递归、非递归)实现

本文部分来源于CSDN兰亭风雨大牛的原创.链接为http://blog.csdn.net/ns_code/article/details/12977901 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大,而若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的).下面先简要介绍三种遍历方式的递归实现,再详细介绍三种遍

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最

链表反转的递归和非递归实现方式

链表反转是数据结构的基本功,主要有递归和非递归两种实现方式.我们一一介绍如下: 1. 非递归实现 主要包括如下4步: 1)如果head为空,或者只有head这一个节点,return head即可: 2)从头到尾遍历链表,把reversedHead赋值给当前节点的next: 3)当前节点赋值给reversedHead: 4)遍历结束,return reversedHead. 下图试图来辅助说明: 代码如下: node* reverseList(node* head) { if(head == NU

二叉树之AVL树的平衡实现(递归与非递归)

这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八种情况对应平衡实现. [1] 情况1-2: 这种需要旋转的结构一般称之为LL型,需要右旋 (顺时针旋转). 我用一个图来抽象一下这两个情况,画的不好,我尽量表达吧. 此时需要对A进行平衡操作,方法为: 将A的左子树换为B的右子树. B的右子树换为A. 非递归实现的代码为: 1 void rotate

C实现二叉树(模块化集成,遍历的递归与非递归实现)

C实现二叉树模块化集成 实验源码介绍(源代码的总体介绍):header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明.LinkStack.c : 链栈的相关操作函数定义.Queue.c : 循环队列的相关操作函数定义.BinTree.c : 二叉树的相关操作的函数定义,层序序列生成二叉树,二叉树的前序序列.中序序列.后序序列的递归和非递归实现,求叶子结点的递归与非递归实现,求树高.我目前还是新手且第一次写类似的博客,文章中难免会有错误!如发现错误,望各路大神能够指出!详见源代码

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {