tree traversal (树的遍历) - preorder traversal (前序遍历)

tree traversal (树的遍历) - preorder traversal (前序遍历)

1. tree traversal - 树的遍历

二叉树的遍历 (traversing binary tree) 是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。遍历是将二叉树中的结点信息由非线性排列变为某种意义上的线性排列,遍历操作使非线性结构线性化。

前序遍历 (preorder) - 中序遍历 (inorder) - 后序遍历 (postorder) - 层序遍历 (breadth-first)。

二叉树由根结点、左子树和右子树三部分组成。假设 D、L、R 分别代表遍历根结点、遍历左子树、遍历右子树,则二叉树的遍历方式有 6 种:DLR、DRL、LDR、LRD、RDL、RLD。先遍历左子树和先遍历右子树在算法设计上没有本质区别,如果我们限制了从左到右的习惯方式,那么主要就分为前序遍历 (preorder) - 中序遍历 (inorder) - 后序遍历 (postorder) - 层序遍历 (breadth-first) 四种。

1.1 深度优先搜索 (depth-first search,DFS)

二叉树的深度优先遍历可细分为前序遍历、中序遍历、后序遍历。这三种遍历可以用递归实现,也可使用迭代实现。

  1. DLR - 前序遍历 (根在前,从左往右,一棵树的根永远在左子树前面,左子树永远在右子树前面)。
  2. LDR - 中序遍历 (根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)。
  3. LRD - 后序遍历 (根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)。

前序遍历 (preorder) - 中序遍历 (inorder) - 后序遍历 (postorder) 是针对根节点而言的,左右子树的遍历顺序不变,前序就是根节点最先遍历,然后左右子树。中序是把根节点放在中间遍历。后序是把根节点放在最后遍历。

tree traversal (树的遍历) - preorder traversal (前序遍历)_第1张图片

  1. 根是相对的,对于整棵树而言只有一个根,但对于每棵子树而言,又有自己的根。对于整棵树而言,A 是根,A 分别在前面、中间、后面被遍历到。对于 D,它是 G 和 H 的根。对于 D、G、H 这棵树而言,三种排序顺序分别是 DGH、GDH、GHD。对于 C,它是 E 和 F 的根,三种排序顺序分别是 CEF、ECF、EFC。
  2. 整棵树的起点,从 A 开始,前序遍历的话,一棵树的根永远在左子树前面,左子树又永远在右子树前面。
  3. 二叉树结点的先根序列、中根序列和后根序列中,所有叶子结点的先后顺序一样。

1.2 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)

层序遍历 (breadth-first) 层序遍历是按层从上到下,从左到右遍历。

tree traversal (树的遍历) - preorder traversal (前序遍历)_第2张图片

2. 前序遍历 (preorder)

二叉树有三类节点:父节点,左孩子节点,右孩子节点。前序遍历是先遍历父节点,之后左孩子节点,右孩子节点。中序和后序遍历都是针对父节点的,父节点中间遍历,父节点最后遍历。左右孩子节点的遍历顺序不变。

tree traversal (树的遍历) - preorder traversal (前序遍历)_第3张图片

  1. 遍历节点 0。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第4张图片

  2. 遍历节点 0 的左孩子节点。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第5张图片

  3. 遍历节点 1 的左孩子节点。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第6张图片

  4. 遍历节点 1 的右孩子节点。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第7张图片

节点 0 的整个左孩子完成遍历,开始遍历节点 0 的右孩子节点。

  1. 遍历节点 0 的整个右孩子节点的根节点 2。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第8张图片

  2. 遍历节点 2 的整个左孩子节点,先遍历节点 5,然后节点 5 的左孩子节点 7,结束节点 2 的左孩子。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第9张图片

  3. 然后遍历节点 2 的右孩子。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第10张图片

遍历结果:0,1,3,4,2,5,7,6

3. 迭代实现前序遍历 (preorder)

前序遍历由两部分组成,一个循环遍历左孩子节点,另外一个将右孩子节点入栈。循环遍历左孩子节点,入栈右节点。弹出栈元素,回到循环遍历左孩子节点。

  1. 从根节点开始,遍历头结点的所有左孩子节点,直到最后一个。栈中存储两个右孩子节点,分别是 2,4。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第11张图片

  2. 将节点 4 弹出栈,输出节点 4。 (遍历到节点没有左孩子节点的时候,开始查看栈中是否有元素。栈中有元素则出栈,继续一直遍历左孩子节点,入栈右孩子节点。) 节点4 没有左孩子节点,也没有右孩子节点,不需要额外的操作。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第12张图片

  3. 弹出栈中元素 2,输出。将节点 2 的右孩子节点 6 放入栈中。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第13张图片

  4. 循环遍历节点 2 的左孩子节点 5,然后 7,直到左孩子节点为空。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第14张图片

  5. 弹出栈中元素 6 输出,6 无左右孩子节点,不做其他操作。栈为空,且 6 的左孩子节点为空,结束循环。
    tree traversal (树的遍历) - preorder traversal (前序遍历)_第15张图片

References

https://dsa.cs.tsinghua.edu.cn/~deng/ds/dsacpp/
https://www.programiz.com/dsa/tree-traversal
http://btechsmartclass.com/data_structures/binary-tree-traversals.html
https://me.csdn.net/fanfan199312

你可能感兴趣的:(C,-,GCC)