原文: https://www.programiz.com/dsa/tree-traversal

在本教程中,您将学习不同的树遍历技术。 此外,您还将找到 C,C++ ,Java 和 Python 中不同的树遍历方法的工作示例。

遍历树意味着访问树中的每个节点。 例如,您可能想在树中添加所有值或找到最大的值。 对于所有这些操作,您将需要访问树的每个节点。

线性数据结构(例如数组,队列链表)只有一种读取数据的方法。 但是可以以不同的方式遍历分层数据结构,例如

树的遍历 - 中序,前序和后序 - 图1

树的遍历

让我们考虑一下如何读取上图所示的树元素。

从上到下,从左到右

  1. 1 -> 12 -> 5 -> 6 -> 9

从底部开始,从左到右

  1. 5 -> 6 -> 12 -> 9 -> 1

尽管此过程有些容易,但它不考虑树的层次结构,而仅考虑节点的深度。

相反,我们使用考虑树的基本结构的遍历方法,即

  1. struct node {
  2. int data;
  3. struct node* left;
  4. struct node* right;
  5. }

leftright指向的结构节点可能还有其他左右子级,因此我们应该将它们视为子树而不是子节点。

根据这种结构,每棵树都是

  • 承载数据的节点
  • 两个子树

树的遍历 - 中序,前序和后序 - 图2

左右子树

请记住,我们的目标是访问每个节点,因此我们需要访问子树中的所有节点,访问根节点以及访问右子树中的所有节点。

根据执行顺序,可以有三种遍历类型。


中序遍历

  1. 首先,访问左侧子树中的所有节点
  2. 然后是根节点
  3. 访问右侧子树中的所有节点
  1. inorder(root->left)
  2. display(root->data)
  3. inorder(root->right)

前序遍历

  1. 访问根节点
  2. 访问左侧子树中的所有节点
  3. 访问右侧子树中的所有节点
  1. display(root->data)
  2. preorder(root->left)
  3. preorder(root->right)

后序遍历

  1. 访问左侧子树中的所有节点
  2. 访问右侧子树中的所有节点
  3. 访问根节点
  1. postorder(root->left)
  2. postorder(root->right)
  3. display(root->data)

让我们可视化顺序遍历。 我们从根节点开始。

树的遍历 - 中序,前序和后序 - 图3

左右子树

我们首先遍历左子树。 我们还需要记住,完成树后,访问根节点和正确的子树。

让我们将所有这些放入中,以便我们记住。

树的遍历 - 中序,前序和后序 - 图4

现在我们遍历指向栈顶部的子树。

同样,我们遵循相同的有序规则

  1. Left subtree -> root -> right subtree

遍历左子树后,我们剩下

树的遍历 - 中序,前序和后序 - 图5

最终栈

由于节点“5”没有任何子树,因此我们直接打印它。 之后,我们先打印其父级“12”,然后打印正确的子级“6”。

将所有内容放到栈上很有帮助,因为现在遍历了根节点的左子树,我们可以将其打印并转到右子树。

遍历所有元素之后,我们得到的有序遍历为

  1. 5 -> 12 -> 6 -> 1 -> 9

我们不必自己创建栈,因为递归可以为我们保持正确的顺序。


Python,Java 和 C/C++ 示例

  1. # Tree traversal in Python
  2. class Node:
  3. def __init__(self, item):
  4. self.left = None
  5. self.right = None
  6. self.val = item
  7. def inorder(root):
  8. if root:
  9. # Traverse left
  10. inorder(root.left)
  11. # Traverse root
  12. print(str(root.val) + "->", end='')
  13. # Traverse right
  14. inorder(root.right)
  15. def postorder(root):
  16. if root:
  17. # Traverse left
  18. postorder(root.left)
  19. # Traverse right
  20. postorder(root.right)
  21. # Traverse root
  22. print(str(root.val) + "->", end='')
  23. def preorder(root):
  24. if root:
  25. # Traverse root
  26. print(str(root.val) + "->", end='')
  27. # Traverse left
  28. preorder(root.left)
  29. # Traverse right
  30. preorder(root.right)
  31. root = Node(1)
  32. root.left = Node(2)
  33. root.right = Node(3)
  34. root.left.left = Node(4)
  35. root.left.right = Node(5)
  36. print("Inorder traversal ")
  37. inorder(root)
  38. print("\nPreorder traversal ")
  39. preorder(root)
  40. print("\nPostorder traversal ")
  41. postorder(root)
  1. // Tree traversal in Java
  2. class Node {
  3. int item;
  4. Node left, right;
  5. public Node(int key) {
  6. item = key;
  7. left = right = null;
  8. }
  9. }
  10. class BinaryTree {
  11. // Root of Binary Tree
  12. Node root;
  13. BinaryTree() {
  14. root = null;
  15. }
  16. void postorder(Node node) {
  17. if (node == null)
  18. return;
  19. // Traverse left
  20. postorder(node.left);
  21. // Traverse right
  22. postorder(node.right);
  23. // Traverse root
  24. System.out.print(node.item + "->");
  25. }
  26. void inorder(Node node) {
  27. if (node == null)
  28. return;
  29. // Traverse left
  30. inorder(node.left);
  31. // Traverse root
  32. System.out.print(node.item + "->");
  33. // Traverse right
  34. inorder(node.right);
  35. }
  36. void preorder(Node node) {
  37. if (node == null)
  38. return;
  39. // Traverse root
  40. System.out.print(node.item + "->");
  41. // Traverse left
  42. preorder(node.left);
  43. // Traverse right
  44. preorder(node.right);
  45. }
  46. public static void main(String[] args) {
  47. BinaryTree tree = new BinaryTree();
  48. tree.root = new Node(1);
  49. tree.root.left = new Node(12);
  50. tree.root.right = new Node(9);
  51. tree.root.left.left = new Node(5);
  52. tree.root.left.right = new Node(6);
  53. System.out.println("Inorder traversal");
  54. tree.inorder(tree.root);
  55. System.out.println("\nPreorder traversal ");
  56. tree.preorder(tree.root);
  57. System.out.println("\nPostorder traversal");
  58. tree.postorder(tree.root);
  59. }
  60. }
  1. // Tree traversal in C
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. struct node {
  5. int item;
  6. struct node* left;
  7. struct node* right;
  8. };
  9. // Inorder traversal
  10. void inorderTraversal(struct node* root) {
  11. if (root == NULL) return;
  12. inorderTraversal(root->left);
  13. printf("%d ->", root->item);
  14. inorderTraversal(root->right);
  15. }
  16. // preorderTraversal traversal
  17. void preorderTraversal(struct node* root) {
  18. if (root == NULL) return;
  19. printf("%d ->", root->item);
  20. preorderTraversal(root->left);
  21. preorderTraversal(root->right);
  22. }
  23. // postorderTraversal traversal
  24. void postorderTraversal(struct node* root) {
  25. if (root == NULL) return;
  26. postorderTraversal(root->left);
  27. postorderTraversal(root->right);
  28. printf("%d ->", root->item);
  29. }
  30. // Create a new Node
  31. struct node* createNode(value) {
  32. struct node* newNode = malloc(sizeof(struct node));
  33. newNode->item = value;
  34. newNode->left = NULL;
  35. newNode->right = NULL;
  36. return newNode;
  37. }
  38. // Insert on the left of the node
  39. struct node* insertLeft(struct node* root, int value) {
  40. root->left = createNode(value);
  41. return root->left;
  42. }
  43. // Insert on the right of the node
  44. struct node* insertRight(struct node* root, int value) {
  45. root->right = createNode(value);
  46. return root->right;
  47. }
  48. int main() {
  49. struct node* root = createNode(1);
  50. insertLeft(root, 12);
  51. insertRight(root, 9);
  52. insertLeft(root->left, 5);
  53. insertRight(root->left, 6);
  54. printf("Inorder traversal \n");
  55. inorderTraversal(root);
  56. printf("\nPreorder traversal \n");
  57. preorderTraversal(root);
  58. printf("\nPostorder traversal \n");
  59. postorderTraversal(root);
  60. }
  1. // Tree traversal in C++
  2. #include <iostream>
  3. using namespace std;
  4. struct Node {
  5. int data;
  6. struct Node *left, *right;
  7. Node(int data) {
  8. this->data = data;
  9. left = right = NULL;
  10. }
  11. };
  12. // Preorder traversal
  13. void preorderTraversal(struct Node* node) {
  14. if (node == NULL)
  15. return;
  16. cout << node->data << "->";
  17. preorderTraversal(node->left);
  18. preorderTraversal(node->right);
  19. }
  20. // Postorder traversal
  21. void postorderTraversal(struct Node* node) {
  22. if (node == NULL)
  23. return;
  24. postorderTraversal(node->left);
  25. postorderTraversal(node->right);
  26. cout << node->data << "->";
  27. }
  28. // Inorder traversal
  29. void inorderTraversal(struct Node* node) {
  30. if (node == NULL)
  31. return;
  32. inorderTraversal(node->left);
  33. cout << node->data << "->";
  34. inorderTraversal(node->right);
  35. }
  36. int main() {
  37. struct Node* root = new Node(1);
  38. root->left = new Node(12);
  39. root->right = new Node(9);
  40. root->left->left = new Node(5);
  41. root->left->right = new Node(6);
  42. cout << "Inorder traversal ";
  43. inorderTraversal(root);
  44. cout << "\nPreorder traversal ";
  45. preorderTraversal(root);
  46. cout << "\nPostorder traversal ";
  47. postorderTraversal(root);