二叉树的前、中、后序遍历与层序遍历

本文详细介绍了二叉树的四种基本遍历方式:前序(根-左-右)、中序(左-根-右)、后序(左-右-根)和层序(逐层从左到右)。通过实例演示和代码实现,帮助理解并掌握这四种遍历算法的应用。

前言

遍历是二叉树的最重要的操作之一,是二叉树进行其他运算的基础,本文将详细讲解遍历二叉树的常用的四种方式。

一、前序遍历

前序遍历也叫先序遍历,它的遍历顺序是:

根节点——> 根节点的左子树 ——> 根节点的右子树

举个栗子:

上图中的二叉树,使用前序遍历的结果为:A B D C E F

那么如何把前序遍历转换为代码呢?

前序遍历的顺序是:根→左→右,所以首先应该打印的是根节点

public void preOrder(TreeNode root) {
        if (root == null) return;//如果节点为空,返回
        System.out.print(root.val + " ");//打印根节点
    }

然后再打印左子树和右子树,但是根节点的左子树和右子树也可以被看作一棵二叉树

很明显,这是一种递归,转换为代码: 

//前序遍历
public void preOrder(TreeNode root) {
        if (root == null) return;//如果节点为空,返回
        System.out.print(root.val + " ");//打印根节点
        preOrder(root.left);//递归打印根的左子树
        preOrder(root.right);//递归打印根的右子树
    }

把这个递归展开的话就是这样:

对照这张图看方便一点:

图画的有点凌乱,大家不要介意哈~

二、中序遍历

中序遍历的遍历顺序是:

根的左子树——>根——>根的右子树

举个粒子:

上图中的二叉树,使用中序遍历的结果为:D B A E C F

转换为代码: 

//中序遍历
void inOrder(TreeNode root) {
        if (root == null) return;
        inOrder(root.left);//递归左子树
        System.out.print(root.val + " ");//打印
        inOrder(root.right);//递归右子树
    }

中序遍历逻辑和前序遍历类似,这里就不再画递归展开图了~

三、后序遍历

后序遍历的遍历顺序是:

根的左子树——>根的右子树——>根

举个李子:

上图中的二叉树,使用后序遍历的结果为:D B E F C A

转换为代码:

//后序遍历
void postOrder(TreeNode root) {
        if (root == null) return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val + " ");
    }

四、层序遍历

层序遍历的遍历顺序是:

从上到下,从左到右,逐层的遍历。

上图中的二叉树,使用层序遍历的结果为:A B C D E F

要把层序遍历转换为代码,我们需要借助一个队列

如果二叉树的根不为空,那么就把根放入到队列中:

此时队列不为空,弹出队列顶部元素,如果队列顶部元素的左子树或右子树不为空,那么就把左子树和右子树放入到队列中

此时队列中有两个元素:B和C,队列不为空,我们继续弹出队列顶部元素并把队列顶部元素的左右子树放到队列中:

此时队列中有两个元素:C和D,队列不为空,我们继续弹出队列顶部元素并把队列顶部元素的左右子树放到队列中:

通过这样不断地循环,直到队列内所有元素都被弹出,队列为空时,就停止循环。

这样,我们就实现了从上到下,从左到右,逐层访问每一个节点,即层序遍历。

转换为代码:

//层序遍历
    public void levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        if(root == null) return;//根节点如果为空,返回
        queue.offer(root);//把根节点放入到队列中
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();//弹出队列顶部元素
            System.out.print(cur.val + " ");
            if(cur.left != null){
                queue.offer(cur.left);//顶部元素的左子树入队
            }
            if(cur.right != null){
                queue.offer(cur.right);//顶部元素的右子树入队
            }
        }
    }

以上就是遍历二叉树的四种方式~

### 上机结果分析 #### 二叉树创建 - **顺序表存储创建**:通过按层次从左往右输入节点值,0 表示空节点,能方便地构建二叉树。但输入错误的数据格式,如非数字或不符合层次顺序,可能导致程序无法正确解析输入,构建出错误的二叉树结构。输入节点数量超过预设的 `NODENUM` 可能会引发数组越界错误,导致程序崩溃或产生不可预期的结果。 - **链式存储创建**:手动创建节点和连接节点构建二叉树,对于小规模二叉树,逻辑清晰,易于理解和实现。但对于大规模二叉树,手动输入节点构建效率极低且容易出错,代码的可维护性也较差。可以考虑通过文件输入来构建链式存储的二叉树,从文件中读取节点信息,提高构建效率。 #### 遍历结果 - **先序遍历(根左右)**:按照根节点、左子树、右子树的顺序访问节点。例如先序遍历代码: ```c void PreOrder(BTNode* root) { if (root == NULL) { return; } printf("%d ", root->data); PreOrder(root->left); PreOrder(root->right); } ``` 先序遍历结果能快速确定树的根节点,对于复制二叉树等操作有重要作用。 - **中序遍历(左根右)**:先访问左子树,再访问根节点,最后访问右子树。示例代码: ```c void InOrder(BTNode* root) { if (root == NULL) { printf("NULL "); return; } InOrder(root->left); printf("%d ", root->data); InOrder(root->right); } ``` 中序遍历对于二叉搜索树能按从小到大的顺序输出节点值,可用于对二叉搜索树进行排序验证。 - **后序遍历(左右根)**:先访问左子树,再访问右子树,最后访问根节点。后序遍历代码示例: ```c void PostOrder(BTNode* root) { if (root == NULL) { return; } PostOrder(root->left); PostOrder(root->right); printf("%d ", root->data); } ``` 后序遍历常用于释放二叉树的内存,因为需要先释放子树节点再释放根节点。 - **层序遍历**:利用队列实现,按层次从左往右依次访问节点。通过队列辅助,能很好地实现广度优先遍历。相关原理及代码可参考“C语言实现二叉树层序遍历(附带源码)”[^1]。层序遍历能直观展示二叉树的层次结构,对于判断完全二叉树等有重要作用。 ### 总结 - **功能实现**:通过不同的遍历方式,可以从不同角度访问二叉树的节点,每种遍历方式都有其特定的应用场景。顺序表存储和链式存储各有优缺点,应根据实际需求选择合适的存储方式。 - **问题改进**:手动构建大规模二叉树效率低,可考虑通过文件输入或其他自动化方式构建。输入数据格式错误会影响二叉树的正确构建,可增加输入验证机制,提高程序的健壮性。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃点橘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值