二叉树逐层遍历

博客介绍了二叉树逐层遍历,强调目的并非二叉树本身,而是结合刚学的STL进行应用,并给出了实现二叉树逐层遍历的代码,利用队列存储节点,按层输出节点数据。

二叉树逐层遍历其实是很简单的东东,拿出来的目的不是为了2叉树,而是刚看过STL,这里可以用到,所以就写出来了

void leveorder(NODE * root)

{

      queue<NODE *> a;

       NODE *p = root;

       while(p)

      {
              cout<<p->data<<endl;

              if(p->left)

              a.push(p->left);

              if(p->right)

              a.push(p->right);

              if(a.empy())

                   break;

              p = a.front();

              a.pop();

       }

}

以下是二叉树四种遍历方法的详细分析及代码实现(使用C语言): --- ### **1. 先序遍历(Preorder Traversal)** **规则**:根节点 → 左子树 → 右子树 **应用场景**:复制二叉树、计算前缀表达式。 #### **递归实现** ```c void PreorderTraversal(TreeNode *root) { if (root == NULL) return; printf("%d ", root->data); // 访问根节点 PreorderTraversal(root->left); // 遍历左子树 PreorderTraversal(root->right); // 遍历右子树 } ``` #### **非递归实现(栈)** ```c void PreorderTraversalNonRecursive(TreeNode *root) { if (root == NULL) return; Stack s; InitStack(&s); Push(&s, root); while (!StackEmpty(s)) { TreeNode *node = Pop(&s); printf("%d ", node->data); // 先右后左,保证左子树先处理 if (node->right) Push(&s, node->right); if (node->left) Push(&s, node->left); } } ``` --- ### **2. 中序遍历(Inorder Traversal)** **规则**:左子树 → 根节点 → 右子树 **特点**:输出二叉搜索树(BST)的节点值是升序的。 #### **递归实现** ```c void InorderTraversal(TreeNode *root) { if (root == NULL) return; InorderTraversal(root->left); // 遍历左子树 printf("%d ", root->data); // 访问根节点 InorderTraversal(root->right); // 遍历右子树 } ``` #### **非递归实现(栈)** ```c void InorderTraversalNonRecursive(TreeNode *root) { Stack s; InitStack(&s); TreeNode *node = root; while (node != NULL || !StackEmpty(s)) { // 遍历到最左节点 while (node != NULL) { Push(&s, node); node = node->left; } node = Pop(&s); printf("%d ", node->data); // 访问节点 node = node->right; // 转向右子树 } } ``` --- ### **3. 后序遍历(Postorder Traversal)** **规则**:左子树 → 右子树 → 根节点 **应用场景**:删除二叉树、计算后缀表达式。 #### **递归实现** ```c void PostorderTraversal(TreeNode *root) { if (root == NULL) return; PostorderTraversal(root->left); // 遍历左子树 PostorderTraversal(root->right); // 遍历右子树 printf("%d ", root->data); // 访问根节点 } ``` #### **非递归实现(双栈法)** ```c void PostorderTraversalNonRecursive(TreeNode *root) { if (root == NULL) return; Stack s1, s2; InitStack(&s1); InitStack(&s2); Push(&s1, root); while (!StackEmpty(s1)) { TreeNode *node = Pop(&s1); Push(&s2, node); // 根节点先入s2 // 左子树先入s1,保证右子树先处理 if (node->left) Push(&s1, node->left); if (node->right) Push(&s1, node->right); } // 逆序输出s2 while (!StackEmpty(s2)) { printf("%d ", Pop(&s2)->data); } } ``` --- ### **4. 逐层遍历(Level Order Traversal)** **规则**:按层级从上到下、从左到右访问节点 **应用场景**:计算二叉树深度、寻找最短路径。 #### **实现(队列)** ```c void LevelOrderTraversal(TreeNode *root) { if (root == NULL) return; Queue q; InitQueue(&q); EnQueue(&q, root); while (!QueueEmpty(q)) { int levelSize = QueueSize(q); for (int i = 0; i < levelSize; i++) { TreeNode *node = DeQueue(&q); printf("%d ", node->data); if (node->left) EnQueue(&q, node->left); if (node->right) EnQueue(&q, node->right); } } } ``` --- ### **遍历规则对比** | 遍历方式 | 访问顺序 | 递归终止条件 | 非递归核心数据结构 | |------------|------------------------|--------------------|--------------------| | 先序遍历 | 根 → 左 → 右 | `root == NULL` | 栈(后进先出) | | 中序遍历 | 左 → 根 → 右 | `node == NULL` | 栈(模拟递归) | | 后序遍历 | 左 → 右 → 根 | `root == NULL` | 双栈(逆序输出) | | 逐层遍历 | 按层级从左到右 | 队列为空 | 队列(先进先出) | --- ### **边界情况测试** 1. **空树**: ```c TreeNode *root = NULL; PreorderTraversal(root); // 无输出 ``` 2. **单节点树**: ```c TreeNode *root = CreateNode(1); InorderTraversal(root); // 输出:1 ``` 3. **左斜树/右斜树**: ```c TreeNode *root = CreateNode(1); root->left = CreateNode(2); root->left->left = CreateNode(3); PostorderTraversal(root); // 输出:3 2 1 ``` --- ### **扩展问题** 1. 如何用Morris遍历实现O(1)空间复杂度的中序遍历? 2. 逐层遍历时如何区分每一层的节点(如“之字形打印”)? 3. 后序遍历的非递归实现能否用单栈完成? 4. 如果二叉树节点数极大(如10^6),递归遍历会导致什么问题? 5. 遍历过程中如何动态修改树结构(如删除节点)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值