欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

程序员文章站 2022-04-27 11:20:43
...

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

1. 前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

  • 遍历的递归实现。
  • 遍历的非递归实现 - 使用栈的非递归实现。
  1. 二叉树的深度优先遍历的非递归做法是采用栈,广度优先遍历的非递归做法是采用队列。
  2. 深度优先对每一个可能的分支路径深入到不能再深入为止,先序遍历、中序遍历、后序遍历属于深度优先遍历。
  3. 广度优先遍历也称为层次遍历,从上往下,从左往右访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。
typedef struct TREENODE
{
	struct TREENODE *left;
	struct TREENODE *right;
	struct TREENODE *parent;
	int data;
} TreeNode;

2. Example

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

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

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

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

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

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

  1. 设置一个栈,将根节点 push 到栈中。
  2. 循环检测栈是否为空,若不空,则取出栈顶元素,保存其值。
  3. 查看栈顶元素右子节点是否存在,若存在则 push 到栈中。查看栈顶元素左子节点,若存在,则 push 到栈中。
  4. 继续回到 2. 执行,直到栈空。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

5.2 Example

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

  1. 设置一个栈,将根节点 push 到栈中 (push(root))。
  2. node = pop(), list.add(node.val)
  3. push(node.right)
  4. push(node.left)
  5. 循环步骤 3. 直到栈空。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

6. 中序遍历 (inorder traversal)

二叉树的深度优先遍历的非递归做法是采用栈 (stack)。
首先中序遍历根结点的左子树,然后访问根结点,最后中序遍历其右子树。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

  1. 设置一个栈。
  2. 将根节点 root,以及 root 的左孩子都压入栈中。
  3. node = pop(), list.add(node.val)
  4. root = node.right
  5. 循环步骤 2. 直到栈为空且 rootNULL

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

7. 后序遍历 (postorder traversal)

二叉树的深度优先遍历的非递归做法是采用栈 (stack)。
首先后序遍历根结点的左子树,然后后序遍历根结点的右子树,最后访问根结点。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

  1. 设置一个栈,将根节点 push 到栈中 (push(root))。
  2. node = pop()
  3. list.add(0 , node.val)
  4. push(node.left)
  5. push(node.right)
  6. 循环步骤 2. 直到栈空。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)