入门级-数据结构-2、简单树:二叉树的遍历(前序、中序、后序)

入门级-数据结构-2、简单树:二叉树的遍历(前序、中序、后序)

一、基本概念

二叉树:一种特殊的树形数据结构,每个节点最多只有两个子节点,分别称为左子节点和右子节点。

// 二叉树节点的基本结构

typedef struct TreeNode {

int data; // 节点存储的数据

struct TreeNode* left; // 指向左子节点的指针

struct TreeNode* right; // 指向右子节点的指针

} TreeNode;

三种遍历方式的概念

遍历是指按照某种顺序访问树中的每一个节点,且每个节点只访问一次。

  1. 前序遍历(Preorder Traversal)
    访问顺序:根节点 → 左子树 → 右子树

执行过程:

访问根节点

前序遍历左子树(递归)

前序遍历右子树(递归)

示例:

1 前序遍历结果:1 → 2 → 4 → 5 → 3

/ \

2 3

/ \

4 5

访问顺序:

步骤1: 访问根节点 1

步骤2: 进入左子树(以2为根)→ 访问2

步骤3: 进入2的左子树 → 访问4

步骤4: 返回,进入2的右子树 → 访问5

步骤5: 返回,进入1的右子树 → 访问3

  1. 中序遍历(Inorder Traversal)
    访问顺序:左子树 → 根节点 → 右子树

执行过程:

中序遍历左子树(递归)

访问根节点

中序遍历右子树(递归)

示例:

1 中序遍历结果:4 → 2 → 5 → 1 → 3

/ \

2 3

/ \

4 5

访问顺序:

步骤1: 进入1的左子树(以2为根)

步骤2: 进入2的左子树 → 访问4

步骤3: 返回,访问2

步骤4: 进入2的右子树 → 访问5

步骤5: 返回,访问1

步骤6: 进入1的右子树 → 访问3

  1. 后序遍历(Postorder Traversal)
    访问顺序:左子树 → 右子树 → 根节点

执行过程:

后序遍历左子树(递归)

后序遍历右子树(递归)

访问根节点

示例:

1 后序遍历结果:4 → 5 → 2 → 3 → 1

/ \

2 3

/ \

4 5

访问顺序:

步骤1: 进入1的左子树(以2为根)

步骤2: 进入2的左子树 → 访问4

步骤3: 进入2的右子树 → 访问5

步骤4: 返回,访问2

步骤5: 进入1的右子树 → 访问3

步骤6: 返回,访问1

二、代码实现

首先,我们需要定义二叉树的节点结构

#include <stdio.h>

#include <stdlib.h>

// 二叉树节点结构

typedef struct TreeNode {

int data; // 节点数据

struct TreeNode* left; // 左子树指针

struct TreeNode* right; // 右子树指针

} TreeNode;

// 创建新节点

TreeNode* createNode(int data) {

TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));

newNode->data = data;

newNode->left = NULL;

newNode->right = NULL;

return newNode;

}

前序遍历(根左右)

// 前序遍历(递归实现)

c 复制代码
void preorderTraversal(TreeNode* root) {
    if (root == NULL) {
        return;
    }
    
    printf("%d ", root->data);      // 访问根节点
    preorderTraversal(root->left);   // 遍历左子树
    preorderTraversal(root->right);  // 遍历右子树
}

// 前序遍历(非递归实现,使用栈)

c 复制代码
void preorderTraversalIterative(TreeNode* root) {
    if (root == NULL) return;
    
    TreeNode* stack[100];  // 简单栈实现
    int top = -1;
    
    stack[++top] = root;
    
    while (top >= 0) {
        TreeNode* node = stack[top--];
        printf("%d ", node->data);
        
        // 注意:栈是后进先出,所以先压右子树,再压左子树
        if (node->right) {
            stack[++top] = node->right;
        }
        if (node->left) {
            stack[++top] = node->left;
        }
    }
}

中序遍历(左根右)

c 复制代码
// 中序遍历(递归实现)
void inorderTraversal(TreeNode* root) {
    if (root == NULL) {
        return;
    }
    
    inorderTraversal(root->left);    // 遍历左子树
    printf("%d ", root->data);       // 访问根节点
    inorderTraversal(root->right);   // 遍历右子树
}

// 中序遍历(非递归实现,使用栈)

c 复制代码
void inorderTraversalIterative(TreeNode* root) {
    if (root == NULL) return;
    
    TreeNode* stack[100];
    int top = -1;
    TreeNode* current = root;
    
    while (current != NULL || top >= 0) {
        // 将左子树的所有节点压入栈
        while (current != NULL) {
            stack[++top] = current;
            current = current->left;
        }
        
        // 弹出栈顶节点并访问
        current = stack[top--];
        printf("%d ", current->data);
        
        // 转向右子树
        current = current->right;
    }
}

后序遍历(左右根)

c 复制代码
// 后序遍历(递归实现)
void postorderTraversal(TreeNode* root) {
    if (root == NULL) {
        return;
    }
    
    postorderTraversal(root->left);   // 遍历左子树
    postorderTraversal(root->right);  // 遍历右子树
    printf("%d ", root->data);        // 访问根节点
}

// 后序遍历(非递归实现,使用两个栈)

c 复制代码
void postorderTraversalIterative(TreeNode* root) {
    if (root == NULL) return;
    
    TreeNode* stack1[100];
    TreeNode* stack2[100];
    int top1 = -1, top2 = -1;
    
    stack1[++top1] = root;
    
    while (top1 >= 0) {
        TreeNode* node = stack1[top1--];
        stack2[++top2] = node;
        
        if (node->left) {
            stack1[++top1] = node->left;
        }
        if (node->right) {
            stack1[++top1] = node->right;
        }
    }
    
    // 输出stack2中的节点(逆序)
    while (top2 >= 0) {
        printf("%d ", stack2[top2--]->data);
    }
}

主程序实现

c 复制代码
int main() {
    // 构建示例二叉树:
    //        1
    //       / \
    //      2   3
    //     / \
    //    4   5
    
    TreeNode* root = createNode(1);
    root->left = createNode(2);
    root->right = createNode(3);
    root->left->left = createNode(4);
    root->left->right = createNode(5);
    
    printf("前序遍历(递归): ");
    preorderTraversal(root);  // 输出: 1 2 4 5 3
    printf("\n");
    
    printf("前序遍历(非递归): ");
    preorderTraversalIterative(root);  // 输出: 1 2 4 5 3
    printf("\n\n");
    
    printf("中序遍历(递归): ");
    inorderTraversal(root);   // 输出: 4 2 5 1 3
    printf("\n");
    
    printf("中序遍历(非递归): ");
    inorderTraversalIterative(root);   // 输出: 4 2 5 1 3
    printf("\n\n");
    
    printf("后序遍历(递归): ");
    postorderTraversal(root); // 输出: 4 5 2 3 1
    printf("\n");
    
    printf("后序遍历(非递归): ");
    postorderTraversalIterative(root); // 输出: 4 5 2 3 1
    printf("\n\n");
    
    return 0;
}
相关推荐
明月_清风9 分钟前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go
渡我白衣12 分钟前
并查集:基础认识与模拟实现
android·java·javascript·数据结构·c++·算法·并查集
hetao173383729 分钟前
2026-09-01~09-04 hetao1733837 的刷题记录
c++·算法
Evand J1 小时前
【MATLAB例程,图像滤波5】 反谐波均值滑动窗口滤波(CHMF)图像降噪与质量评价,附代码下载链接
图像处理·算法·计算机视觉·matlab·均值算法·滑动窗口滤波·均值滑动
血小板要健康1 小时前
链表 阶段算法总结
java·数据结构·笔记·算法·leetcode·链表
a187927218311 小时前
【算法】回溯算法(三):三记重锤与 N 皇后——记忆化、状态设计与三层漏斗
算法·leetcode·go·剪枝·回溯·n皇后·算法讲解
HugoStudio_SWAN3 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
青 春 记 忆4 小时前
LeetCode 350. 两个数组的交集 II|Python 解法详解
python·算法·leetcode
阳明山水5 小时前
销量预测2025—2026:从模型竞赛到系统融合的范式转型
人工智能·深度学习·算法·机器学习·架构
桐盛科技5 小时前
拒绝“漂绿”风险:基于边缘计算的碳排放数据清洗算法与实时校验逻辑
人工智能·算法·边缘计算