二叉树先序遍历

下面是leetcode上的一道题,先序遍历二叉树。

Given a binary tree, return the preorder traversal of its nodes' values.

For example:
Given binary tree{1,#,2,3},

   1
    \
     2
    /
   3

 

return[1,2,3].

Note: Recursive solution is trivial, could you do it iteratively?

对于二叉树的遍历,很容易联想到递归,那么第一种思路就是使用递归的思想,参考代码如下:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
 
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> result;
        helper(root,result);
        return result;
 
    }
    void helper(TreeNode *node,vector<int> &result){
        if (node==NULL){
            return;
        }
        result.push_back(node->val);
        helper(node->left,result);
 
        helper(node->right,result);
    }
};

我们再司考一下,先序遍历就是根节点、左子节点、右子节点,那么也可以通过ADT栈来实现。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> res;
        stack<TreeNode *> s;
        if (root == NULL){
            return res;
        }
        s.push(root);
        while (!s.empty()){
            TreeNode *cur = s.top();
            s.pop();
            res.push_back(cur->val);
            if (cur->right!=NULL)
                s.push(cur->right);
            if (cur->left!=NULL)
                s.push(cur->left);
        }
        return res;
    }
};

 

### 二叉树序遍历的原理 序遍历是一种深度优遍历方法,其核心原则是按照“ -> 左 -> 右”的顺序访问二叉树中的节点[^1]。这意味着,在访问任何子之前,总是访问该子节点。 具体来说,对于任意给定的一棵或子: - 首访问节点; - 接着递归地对左子执行相同的序遍历操作; - 最后递归地对右子执行同样的序遍历操作。 这种递归性质使得序遍历非常适合通过递归函数实现[^4]。 --- ### 序遍历的递归实现思路 递归实现的核心在于分解问题为更小的部分,并逐步解决每一个部分。以下是递归实现的具体逻辑: 1. 如果当前节点为空,则直接返回。 2. 否则,首访问当前节点(打印或存储其值)。 3. 对当前节点的左子调用递归函数。 4. 对当前节点的右子调用递归函数。 #### 示例代码 (递归版) ```c void preOrderTraversalRecursive(Node* root) { if (root == NULL) { // 基本情况:遇到空节点停止 return; } printf("%d ", root->data); // 访问节点 preOrderTraversalRecursive(root->left); // 递归遍历左子 preOrderTraversalRecursive(root->right); // 递归遍历右子 } ``` 上述代码展示了如何利用递归来实现序遍历。 --- ### 序遍历的非递归实现思路 虽然递归实现简单直观,但在某些情况下可能因为栈溢出而失效。为了克服这一点,可以通过显式的堆栈模拟递归过程来实现非递归版本的序遍历。 主要步骤如下: 1. 初始化一个辅助栈并将节点压入栈中。 2. 当栈不为空时,重复以下操作: - 弹出栈顶元素并访问它。 - 将弹出节点的右子节点(如果有)压入栈中。 - 将弹出节点的左子节点(如果有)压入栈中。 注意:由于栈的特点是后进出,所以要将右子节点压入栈中,然后再压入左子节点,从而保证左子节点被优处理[^2]。 #### 示例代码 (非递归版) ```c void preOrderTraversalIterative(Node* root) { if (root == NULL) { return; } Stack stack; // 定义一个栈 initStack(&stack); push(&stack, root); while (!isEmpty(&stack)) { Node* node = pop(&stack); // 弹出栈顶元素 printf("%d ", node->data); // 访问节点 if (node->right != NULL) { // 压入右子节点 push(&stack, node->right); } if (node->left != NULL) { // 再压入左子节点 push(&stack, node->left); } } } ``` 此代码片段展示了一种基于栈的非递归解决方案[^2]。 --- ### 结论 无论是递归还是非递归的方式,它们都遵循“ -> 左 -> 右”的基本规则。递归方法更加简洁易懂,而非递归方法则提供了更好的内存控制能力,尤其是在面对深嵌套的二叉树时更为适用。 --- 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HUST_Miao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值