前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)
前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)
1. 前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)
- 遍历的递归实现。
- 遍历的非递归实现 - 使用栈的非递归实现。
- 二叉树的深度优先遍历的非递归做法是采用栈,广度优先遍历的非递归做法是采用队列。
- 深度优先对每一个可能的分支路径深入到不能再深入为止,先序遍历、中序遍历、后序遍历属于深度优先遍历。
- 广度优先遍历也称为层次遍历,从上往下,从左往右访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。
typedef struct TREENODE
{
struct TREENODE *left;
struct TREENODE *right;
struct TREENODE *parent;
int data;
} TreeNode;
2. Example
2.1 前序遍历 (preorder traversal)
首先访问根结点,然后前序遍历其左子树,最后前序遍历其右子树。
遍历结果:A B D H I E J C F G
2.2 中序遍历 (inorder traversal)
首先中序遍历根结点的左子树,然后访问根结点,最后中序遍历其右子树。
遍历结果:H D I B J E A F C G
2.3 后序遍历 (postorder traversal)
首先后序遍历根结点的左子树,然后后序遍历根结点的右子树,最后访问根结点。
遍历结果:H I D J E B F G C A
3. Example
3.1 中序遍历 (inorder traversal)
首先中序遍历根结点的左子树,然后访问根结点,最后中序遍历其右子树。
遍历结果:B D C A E H G K F
我们从根节点 A 看起,遍历 A 的左子树。
A 的左子树存在,找到 B,此时 B 看做根节点,遍历 B 的左子树。
B 的左子树不存在,返回 B,根据 [左根右]
的遍历规则,记录 B,遍历 B 的右子树。
B 的右子树存在,找到 C,此时 C 看做根节点,遍历 C 的左子树。
C 的左子树存在,找到 D。由于 D 是叶子节点,无左子树,记录 D。D 无右子树,返回 C,根据 [左根右]
的遍历规则,记录 C,遍历 C 的右子树。
C 的右子树不存在,返回 B,B 的右子树遍历完,返回 A。A 的左子树遍历完毕,根据 [左根右]
的遍历规则,记录 A,遍历 A 的右子树。
A 的右子树存在,找到 E,此时 E 看做根节点,遍历 E 的左子树。
E 的左子树不存在,返回 E,根据 [左根右]
的遍历规则,记录 E,遍历 E 的右子树。
E 的右子树存在,找到 F,此时 F 看做根节点,遍历 F 的左子树。
F 的左子树存在,找到 G,此时 G 看做根节点,遍历 G 的左子树。
G 的左子树存在,找到 H,由于 H 是叶子节点,无左子树,记录 H。H 无右子树,返回 G,根据 [左根右]
的遍历规则,记录 G,遍历 G 的右子树。
G 的右子树存在,找到 K,由于 K 是叶子节点,无左子树,记录 K。K 无右子树,返回 G,根据 [左根右]
的遍历规则,记录 F,遍历 F的右子树。
F 的右子树不存在,返回 F,E 的右子树遍历完毕,返回 A。A 的右子树也遍历完毕。
遍历结果:B D C A E H G K F
4. Example
4.1 前序遍历 (preorder traversal)
首先访问根结点,然后前序遍历其左子树,最后前序遍历其右子树。
遍历结果:A B D E G H C F
4.2 中序遍历 (inorder traversal)
首先中序遍历根结点的左子树,然后访问根结点,最后中序遍历其右子树。
遍历结果:D B G E H A C F
4.3 后序遍历 (postorder traversal)
首先后序遍历根结点的左子树,然后后序遍历根结点的右子树,最后访问根结点。
遍历结果:D G H E B F C A
4.4 层序遍历 (breadth-first traversal)
遍历结果:A B C D E F G H
前序、中序、后序是针对根节点而言的,左右子树的遍历顺序不变。前序就是根节点最先遍历,然后左右子树。中序就是根节点放在中间遍历。后序就是把根节点放在最后遍历。
5. 前序遍历 (preorder traversal)
二叉树的深度优先遍历的非递归做法是采用栈 (stack)。
首先访问根结点,然后前序遍历其左子树,最后前序遍历其右子树。
5.1 Example
- 设置一个栈,将根节点 push 到栈中。
- 循环检测栈是否为空,若不空,则取出栈顶元素,保存其值。
- 查看栈顶元素右子节点是否存在,若存在则 push 到栈中。查看栈顶元素左子节点,若存在,则 push 到栈中。
- 继续回到 2. 执行,直到栈空。
5.2 Example
- 设置一个栈,将根节点 push 到栈中 (
push(root)
)。 node = pop(), list.add(node.val)
push(node.right)
push(node.left)
- 循环步骤
3.
直到栈空。
6. 中序遍历 (inorder traversal)
二叉树的深度优先遍历的非递归做法是采用栈 (stack)。
首先中序遍历根结点的左子树,然后访问根结点,最后中序遍历其右子树。
- 设置一个栈。
- 将根节点 root,以及 root 的左孩子都压入栈中。
node = pop(), list.add(node.val)
root = node.right
- 循环步骤
2.
直到栈为空且root
为NULL
。
7. 后序遍历 (postorder traversal)
二叉树的深度优先遍历的非递归做法是采用栈 (stack)。
首先后序遍历根结点的左子树,然后后序遍历根结点的右子树,最后访问根结点。
- 设置一个栈,将根节点 push 到栈中 (
push(root)
)。 node = pop()
list.add(0 , node.val)
push(node.left)
push(node.right)
- 循环步骤
2.
直到栈空。
上一篇: 好笑好玩的冷幽默
下一篇: 企业网站怎么做好推广工作
推荐阅读
-
tree traversal (树的遍历) - 中序遍历 (inorder traversal) - 二叉树的中序遍历
-
tree traversal (树的遍历) - 前序遍历 (preorder traversal) - 二叉树的前序遍历
-
tree traversal (树的遍历) - 前序遍历 (preorder traversal) - 对称二叉树
-
leetcode: binary-tree-postorder-traversal:后序遍历二叉树
-
中序遍历 94. Binary Tree Inorder Traversal
-
LeetCode145. Binary Tree Postorder Traversal(后序遍历)
-
LeetCode-145. Binary Tree Postorder Traversal(实现后序遍历)(三种非递归方式)
-
前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)
-
LeetCode 144. Binary Tree Preorder Traversal-二叉树的前序遍历(JAVA迭代及递归方法实现)