PTA(树和二叉树)1-7 二叉树的非递归遍历
PTA(树和二叉树)1-7 二叉树的非递归遍历
zhangzhang1-7 二叉树的非递归遍历
分数 5
作者 陈越
单位 浙江大学
本题要求用非递归的方法实现对给定二叉树的 3 种遍历。
函数接口定义:
1 | void InorderTraversal( BinTree BT ); |
其中BinTree结构定义如下:
1 | typedef struct TNode *Position; |
要求 3 个函数分别按照访问顺序打印出结点的内容,格式为一个空格跟着一个字符。
此外,裁判程序中给出了堆栈的全套操作,可以直接调用。
裁判测试程序样例:
1 |
|
输入样例:
1 | 如图 |
输出样例:
1 | Inorder: D B E F A G H C I |
- 非递归跟前面的递归真的是两个级别,非递归用到栈了,直接上强度了
- 递归只用思考根在哪个位置,然后写出终结条件就可以了
- 而非递归需要像思考:比如中序序列怎么列出来的思路,完整的用代码实现自己的逻辑
- 这题用栈很妙,让p先指向根节点,都是一个while套一个while
- 遍历左子树直到空,期间将根节点依次入栈,用来下一次出栈访问上一个结点的信息
- 前序遍历:先访问根节点,再遍历左子树,最后遍历右子树(根 → 左 → 右)。
- 中序遍历:先遍历左子树,再访问根节点,最后遍历右子树(左 → 根 → 右)。
- 后序遍历:先遍历左子树,再遍历右子树,最后访问根节点(左 → 右 → 根)。
答案
1 | void InorderTraversal( BinTree BT ) { |
代码解析
- 中序遍历(InorderTraversal)
- 逻辑:先将所有左子树节点入栈,直到最左节点;弹出栈顶节点(此时左子树已遍历完),访问该节点(根节点),再转向其右子树重复上述过程。
- 关键:根节点的访问时机在左子树遍历完成后。
- 前序遍历(PreorderTraversal)
- 逻辑:在遍历左子树的过程中,每遇到一个节点就立即访问(根节点优先),然后将节点入栈(用于后续访问右子树);左子树遍历完后,弹出栈顶节点并转向其右子树。
- 关键:根节点的访问时机在左子树遍历之前。
- 后序遍历(PostorderTraversal)
- 逻辑:通过节点的
flag标记控制访问时机。首次入栈时flag=0(未访问右子树),弹出时若flag=0,则标记为1并转向右子树;再次遇到flag=1的节点时,说明右子树已遍历完,此时访问该节点。 - 关键:根节点的访问时机在左右子树均遍历完成后,需通过标记区分节点是否已处理右子树。
- 逻辑:通过节点的
结构含义
1. 核心数据结构:二叉树节点(struct TNode)
这是整个结构的基础,用于存储二叉树的每个节点信息:
ElementType Data:存储节点的数据(这里通过typedef定义为char类型,即节点存储字符数据)。BinTree Left和BinTree Right:分别指向当前节点的左子树和右子树(BinTree本质是指向TNode的指针,即Position)。int flag:节点的标记位(通常用于遍历等操作中标记节点状态,例如是否已访问)。
2. 类型别名:简化指针表示
通过 typedef 定义了三个别名,本质都是指针类型,目的是简化代码书写并明确语义:
Position:等价于struct TNode *,表示 “二叉树节点的位置(指针)”。BinTree:等价于Position(即struct TNode *),专门用于表示 “二叉树”(通常指向根节点)。ElementType:等价于char,明确节点存储的数据类型(后续若需修改数据类型,只需修改此处即可)。
3. 辅助结构:堆栈(struct SNode 及相关类型)
堆栈用于辅助二叉树的操作(例如非递归遍历),其设计与二叉树节点强关联:
SElementType:堆栈中存储的元素类型,被定义为Position(即二叉树节点的指针),说明这个堆栈是专门用于存放二叉树节点地址的。- struct SNode:堆栈的节点结构,包含:
SElementType Data:存储一个二叉树节点的指针(即栈元素是二叉树节点的位置)。PtrToSNode Next:指向栈的下一个节点(构成链式堆栈)。
Stack:等价于PtrToSNode,表示 “堆栈”(通常指向栈顶节点)。



