1. 二叉树遍历基础概念
二叉树是一种重要的非线性数据结构,在计算机科学中有着广泛的应用。遍历二叉树意味着按照某种顺序访问树中的所有节点,确保每个节点被访问且仅被访问一次。常见的遍历方式包括前序遍历、中序遍历、后序遍历和层次遍历。
二叉树节点的典型结构包含三个部分:数据域(存储节点值)、左指针(指向左子树)和右指针(指向右子树)。在C语言中,我们通常这样定义二叉树节点:
c复制typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
理解遍历顺序的关键在于把握"访问节点"的时机。以中序遍历为例,它的访问顺序是:左子树→根节点→右子树。这种顺序在二叉搜索树中特别有用,因为它能按升序输出所有节点。
提示:在实际编程中,递归实现遍历代码简洁但可能栈溢出,非递归实现(使用栈或队列)效率更高但代码复杂些。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 非递归遍历实现详解
2.1 中序遍历的非递归实现
中序遍历的非递归算法需要借助栈来模拟递归调用。基本思路是:
- 从根节点开始,将所有左子节点压栈
- 弹出栈顶节点并访问
- 转向该节点的右子树
- 重复上述过程直到栈空且当前节点为空
c复制void InorderTraversal(BinTree BT){
BinTree s[100]; // 模拟栈的数组
int top = -1; // 栈顶指针
BinTree p = BT; // 当前节点指针
if(p==NULL) return;
while(p!=NULL || top!=-1){
if(p!=NULL){
s[++top] = p; // 压栈
p = p->Left; // 转向左子树
}else{
p = s[top--]; // 弹出栈顶
printf(" %c",p->Data); // 访问节点
p = p->Right; // 转向右子树
}
}
}
这个实现有几个关键点:
- 栈大小设为100,对于教学示例足够,实际应用中应考虑动态扩容
- 循环条件
p!=NULL || top!=-1确保所有节点都被处理 - 访问节点时机在弹出栈顶后,保证"左→根→右"的顺序
2.2 前序遍历的非递归实现
前序遍历的顺序是:根节点→左子树→右子树。非递归实现同样使用栈,但与中序遍历有所不同:
c复制void PreorderTraversal(BinTree BT){
BinTree s[100];
int top = -1;
BinTree p = BT;
if(p==NULL) return;
s[++top] = p; // 根节点入栈
while(top!=-1){
p = s[top--]; // 弹出栈顶
printf(" %c",p->Data); // 先访问
// 右子节点先入栈(后处理)
if(p->Right) s[++top] = p->Right;
// 左子节点后入栈(先处理)
