二叉树的遍历方式

1 深度优先

1.1 前序遍历

(leetcode 144题)

前序遍历即为当遍历一棵树时, 先遍历自身节点, 然后遍历其左子树, 最后是其右子树

1.1.1 递归实现

递归实现很好实现了, 不需要写了

1.1.2 非递归实现

先序遍历的非递归版本需要用到栈, 因为自身先遍历, 所以先放入自身, 每次遍历时先遍历自身, 如果有右子节点, 栈压入右子节点, 如果有左子节点, 栈压入左子节点(因为遍历顺序为自身->左子树->右子树, 后入先出, 所以先压入右节点)

代码:

vector<int> preorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> t_stack;
    if (root) {
        t_stack.push(root);
    }
    while (!t_stack.empty()) {
        TreeNode* node = t_stack.top();
        t_stack.pop();
        res.push_back(node->val);
        if (node->right)
            t_stack.push(node->right);
        if (node->left)
            t_stack.push(node->left);
    }
    return res;
}

1.2 中序遍历

(leetcode 94题)

1.2.1 递归实现

1.2.2 非递归实现

二叉树中序遍历的非递归(迭代)版本, 就比较麻烦了, 首先要确定的是顺序: 左子树->节点->右子树, 所以只要左子树有子节点, 就一直让其入栈, 直到没有左子节点, 则遍历自身, 然后将其右节点入栈, 重复上述过程.

代码:

vector<int> inorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> t_stack;
    while (root || !t_stack.empty()) {
        while (root) {
            t_stack.push(root);
            root = root->left;
        }
        root = t_stack.top();
        t_stack.pop();
        res.push_back(root->val);
        root = root->right;
    }
    return res;
}

1.3 后续遍历

(leetcode 145题)

1.3.1 递归实现

1.3.2 非递归实现

后续遍历同样可以用栈来实现, 但是会比前序遍历更复杂一些. 首先, 后续遍历的顺序为左子树->右子树->自身节点, 所以思路是, 设计一个栈, 入栈顺序为: 节点自身->节点右节点->节点左节点. 这样遍历的话就是左->右->自身了. 遍历的规则是, 如果这个节点是叶子节点, 还有一个条件, 就是子节点已经遍历过了, 那么就遍历该节点, 否则就是左右子节点入栈. 那么怎么确定每个节点的左右子节点是否遍历过呢, 可以每遍历一个节点都记录一下当前遍历的节点, 这样在检查一个节点的子节点是否遍历过时, 就看上一个遍历过的节点是不是自己的左右子节点就可以.

代码:

vector<int> postorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> t_stack;
    if (root) {
        t_stack.push(root);
    }
    TreeNode* prev = nullptr;
    while (!t_stack.empty()) {
        TreeNode *node = t_stack.top();
        //如果是叶子节点, 或者子节点已经遍历过(prev是当前的子节点)
        if ((!node->left && !node->right) || (prev && (prev == node->left || prev == node->right))) {
            //遍历, prev置为当前node, 退栈
            res.push_back(node->val);
            prev = node;
            t_stack.pop();
        } else {
            if (node->right)
                t_stack.push(node->right);
            if (node->left)
                t_stack.push(node->left);
        }
    }
    return res;
}

2 广度优先(层序遍历)

(leetcode 102题)

二叉树层序遍历, 以层为优先, 可以以队列的方式进行.

代码:

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> res;
    if (root) {
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            int l_c = q.size();
            vector<int> l_res;
            for (int i = 0; i < l_c; i ++) {
                TreeNode* node = q.front();
                q.pop();
                l_res.push_back(node->val);
                if (node->left)
                    q.push(node->left);
                if (node->right)
                    q.push(node->right);
            }
            res.push_back(l_res);
        }
    }
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值