【二叉树】【经典例题及解答】用栈(Stack)对二叉树(Binary Tree)进行前序(Pre)、中序(In)、后序(Post)非递归遍历

定义

在计算机科学中,二叉树(英语:Binary tree)是每个节点最多只有两个分支(即不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”或“右子树”。

堆栈(英语:stack)又称为栈或堆叠,是计算机科学中的一种抽象数据类型,只允许在有序的线性数据集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。因而按照后进先出(LIFO, Last In First Out)的原理运作。

  • Inorder/中序遍历 (Left, Root, Right)
  • Preorder/前序遍历 (Root, Left, Right)
  • Postorder/后序遍历 (Left, Right, Root)

对树的遍历传统方法都采用递归,本文只介绍迭代的方法。使用迭代能够在遍历过程中,根据题意,进行更加细的数据操作。

Preorder Traversal

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

Inorder Traversal

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> _r;
        stack<TreeNode*> _s;
        while(root || _s.size()){
            while(root){
                _s.push(root);
                root = root->left;
            }
            auto _top = _s.top();
            _r.push_back(_top->val);
            _s.pop();
            if(_top->right!=NULL){
                root = _top->right;
            }
        }
        return _r;
    }

Postorder Traversal

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> nodes;
        stack<TreeNode*> todo;
        TreeNode* last = NULL;
        while (root || !todo.empty()) {
            if (root) {
                todo.push(root);
                root = root -> left;
            } else {
                TreeNode* node = todo.top();
                if (node -> right && last != node -> right) {
                    root = node -> right;
                } else {
                    nodes.push_back(node -> val);
                    last = node;
                    todo.pop();
                }
            }
        }
        return nodes;
    }

应用

题目来源于LeetCode

783.Minimum Distance Between BST Nodes

Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the values of any two different nodes in the tree.

Example :

Input: root = [4,2,6,1,3,null,null]
Output: 1
Explanation:
Note that root is a TreeNode object, not an array.

The given tree [4,2,6,1,3,null,null] is represented by the following diagram:

      4
    /   \
  2      6
 / \    
1   3  

while the minimum difference in this tree is 1, it occurs between node 1 and node 2, also between node 3 and node 2.
Note:

The size of the BST will be between 2 and 100.
The BST is always valid, each node’s value is an integer, and each node’s value is different.

题解

此题用应用上文的中序遍历方法

class Solution {
public:
    int _min = INT_MAX;
    int minDiffInBST(TreeNode* root) {
        stack<TreeNode*> _s;
        TreeNode* prev = nullptr;
        while(root || _s.size()){
            while(root){
                _s.push(root);
                root = root->left;
            }
            root = _s.top();
            _s.pop();
            if(prev){
                _min = min(_min, root->val - prev->val);
            }
            prev = root;
            root = root->right;
        }
        return _min;
    }
    
};

113. Path Sum II

Given a non-empty binary tree, find the maximum path sum.

For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.

Example 1:

Input: [1,2,3]

   1
  / \
 2   3

Output: 6

题解

此题用应用上文的中序遍历方法,注意我们用prev保存父节点,因为过早pop父节点不利于解答此题。用tmp->right != prev避免重复遍历。

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        stack<TreeNode*> s;
        vector<vector<int>>r;
        vector<int> ins; int acc = 0;
        TreeNode* prev = nullptr;
        while (root || s.size()) {
            while (root) {
                s.push(root);
                acc += root->val;
                ins.push_back(root->val);
                root = root->left;
            }
            auto tmp = s.top();

            if (!tmp->left && !tmp->right) {
                if (acc == sum) r.push_back(ins);
            }

            if (tmp->right && tmp->right != prev) 
                root = tmp->right;
            else {
                prev = tmp;
                acc -= tmp->val;
                ins.pop_back();
                s.pop();
            }
        }
        return r;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值