在本教程中,您将学习不同的树遍历技术。此外,您还将找到C中树遍历方法的工作示例。(C++,Java和Python示例见原文)
遍历树意味着访问树中的每个节点。例如,您可能想把所有值添加到树中或找到最大的值。对于所有这些操作,您将需要访问树的每个节点。
线性数据结构(如数组,堆栈,队列和链表)只有一种读取数据的方法。但是像树这样的分层数据结构可以以不同的方式遍历。
让我们考虑一下如何在上面显示的图像中读取树的元素。
从上到下,从左到右
1 -> 12 -> 5 -> 6 -> 9
从底部开始,从左到右
5 -> 6 -> 12 -> 9 -> 1
虽然这个过程有点简单,但它不考虑树的层次结构,只考虑节点的深度。
取而代之的是,我们使用遍历方法来考虑树的基本结构,即
struct node {
int data;
struct node* left;
struct node* right;
}
由 left 和 right 指向的struct节点可能有其他的 left 和 right 子节点,因此我们应该将它们看作子树而不是子节点。
根据这种结构,每棵树都是
- 承载数据的节点
- 两个子树
请记住,我们的目标是访问每个节点,因此我们需要访问子树中的所有节点,访问根节点以及访问右子树中的所有节点。
根据执行顺序,可以有三种遍历类型。
中序遍历
- 首先,访问左侧子树中的所有节点
- 然后是根节点
- 访问右侧子树中的所有节点
inorder(root->left)
display(root->data)
inorder(root->right)
前序遍历
- 访问根节点
- 访问左侧子树中的所有节点
- 访问右侧子树中的所有节点
display(root->data)
preorder(root->left)
preorder(root->right)
后序遍历
- 访问左侧子树中的所有节点
- 访问右侧子树中的所有节点
- 访问根节点
postorder(root->left)
postorder(root->right)
display(root->data)
让我们可视化中序遍历。我们从根节点开始。
我们首先遍历左子树。我们还需要记住在这个树完成时访问根节点和正确的子树。
让我们将所有这些放到堆栈中,这样我们就记住了。
现在我们遍历指向堆栈顶部的子树。
同样,我们遵循相同的有序规则。
Left subtree -> root -> right subtree
遍历左子树后,我们将得到:
由于节点“ 5”没有任何子树,因此我们直接打印它。之后,我们先打印其父级“ 12”,然后打印正确的子级“ 6”。
将所有内容放在堆栈中很有帮助,因为现在已经遍历了根节点的左子树,我们可以打印它并转到右子树。
在遍历所有元素之后,我们得到的中序遍历为
5 -> 12 -> 6 -> 1 -> 9
我们不必自己创建堆栈,因为递归可以为我们保持正确的顺序。
C 示例
// Tree traversal in C
#include <stdio.h>
#include <stdlib.h>
struct node {
int item;
struct node* left;
struct node* right;
};
// Inorder traversal
void inorderTraversal(struct node* root) {
if (root == NULL) return;
inorderTraversal(root->left);
printf("%d ->", root->item);
inorderTraversal(root->right);
}
// preorderTraversal traversal
void preorderTraversal(struct node* root) {
if (root == NULL) return;
printf("%d ->", root->item);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
// postorderTraversal traversal
void postorderTraversal(struct node* root) {
if (root == NULL) return;
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%d ->", root->item);
}
// Create a new Node
struct node* createNode(value) {
struct node* newNode = malloc(sizeof(struct node));
newNode->item = value;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Insert on the left of the node
struct node* insertLeft(struct node* root, int value) {
root->left = createNode(value);
return root->left;
}
// Insert on the right of the node
struct node* insertRight(struct node* root, int value) {
root->right = createNode(value);
return root->right;
}
int main() {
struct node* root = createNode(1);
insertLeft(root, 12);
insertRight(root, 9);
insertLeft(root->left, 5);
insertRight(root->left, 6);
printf("Inorder traversal \n");
inorderTraversal(root);
printf("\nPreorder traversal \n");
preorderTraversal(root);
printf("\nPostorder traversal \n");
postorderTraversal(root);
}
编译执行,结果为:
Inorder traversal
5 ->12 ->6 ->1 ->9 ->
Preorder traversal
1 ->12 ->5 ->6 ->9 ->
Postorder traversal
5 ->6 ->12 ->9 ->1 ->
参考文档
https://www.programiz.com/dsa/tree-traversal