144.二分木のプレオーダートラバーサル145.二分木のポストオーダートラバーサル94.二分木のミドルオーダートラバーサル(高度な複数のソリューション)

144.二分木のプレオーダートラバーサル

トピック:

二分木が与えられた場合、そのプレオーダー トラバーサルを返し ます。

例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]

解決策1:再帰

class Solution {
private:
    void takeVal(TreeNode *root, vector<int>& res) {
        if (NULL == root)
            return;
        
        res.push_back(root->val);
        takeVal(root->left, res);
        takeVal(root->right, res);
    }
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        takeVal(root, res);

        return res;
    }
};

解決策2:スタックを使用し、最初に右側のサブツリーを入力してから、左側のサブツリーを入力します

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

            if (node->right)
                sta.push(node->right);
            if (node->left)
                sta.push(node->left);
        }

        return res;
    }
};

解決策3:スタックを使用し、右側のサブツリーのみを押す

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node = root;
        while (true) {
            if (node) {
                res.push_back(node->val);

                if (node->right)
                    sta.push(node->right);
                node = node->left;
            } else {
                if (sta.empty())
                    break;
                
                node = sta.top();
                sta.pop();
            }
        }

        return res;
    }
};

145.二分木のポストオーダートラバーサル

トピック:

二分木が与えられた場合、そのポストオーダー トラバーサルを返し ます。

例:

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [3,2,1]

解決策1:再帰

class Solution {
private:
    void takeVal(TreeNode *root, vector<int>& res) {
        if (NULL == root)
            return;

        takeVal(root->left, res);
        takeVal(root->right, res);
        res.push_back(root->val);
    }
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        takeVal(root, res);

        return res;
    }
};

 解決策2:スタックを使用して左右の子ノードをプッシュします

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node;
        sta.push(root);
        while (!sta.empty()) {
            node = sta.top();
            root = node;             //在处理其子节点前,记住这个节点
            while (node->left) {     //处理左子树
                node = node->left;
                root->left = NULL;   //节点左指针剪枝,避免无限重复访问
                sta.push(node);
                root =node;
            }

            if (root->right) {       //转向右子树,重复处理其左子树
                node = root->right;
                root->right = NULL;  //节点右指针剪枝
                sta.push(node);
                root = node;
            } else {                 //没有左子树,没有右子树,即压入节点
                res.push_back(root->val);
                sta.pop();
            }
        }

        return res;
    }
};

         このソリューションが呼び出された後、ツリー構造が変更されます。つまり、ツリーはノードに分割されます。

解決策3:スタックを使用して左右の子ノードをプッシュし、補助マーカーノードを使用して親ノードと子ノードを分離し、元のツリーを変更しないでください


class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node;
        sta.push(root);
        while (!sta.empty()) {
            node = sta.top();
            if (node) {                    //父节点是栈的top()
                sta.push(NULL);            //在父节点和其孩子节点之间加一个标记
                if (node->right)
                    sta.push(node->right);
                if (node->left)
                    sta.push(node->left);
            } else {
                sta.pop();                 //弹出标记的空节点
                node = sta.top();
                sta.pop();
                res.push_back(node->val);
            }
        }

        return res;
    }
};

解決策4:解決策3に基づいて、前、中、後の順序でトラバースできるテンプレートを作成します

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node;
        sta.push(root);
        while (!sta.empty()) {
            node = sta.top();
            sta.pop();                     //弹出该节点
            if (node) {
                sta.push(node);            //先压入该父节点
                sta.push(NULL); 
                if (node->right)
                    sta.push(node->right);
                if (node->left)
                    sta.push(node->left);
            } else {                      //标记节点已弹出
                node = sta.top();
                sta.pop();
                res.push_back(node->val);
            }
        }

        return res;
    }
};

            現在の親ノードにポップインすることにより、親ノードとその子ノードの相対位置が変更されます。このソリューションは、if(ノード)のステートメントの相互順序をわずかに変更して、プレオーダー、ミドルオーダー、およびポストオーダーのトラバーサルを実現します。

          if(node)を変更し、最後に親ノードを押して、テンプレートの下でプレオーダートラバーサルを取得します。具体的な手順は次のとおりです。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node;
        sta.push(root);
        while (!sta.empty()) {
            node = sta.top();
            sta.pop();
            if (node) {
                if (node->right)
                    sta.push(node->right);
                if (node->left)
                    sta.push(node->left);
                sta.push(node);              //最后压入父节点
                sta.push(NULL);
            } else {
                node = sta.top();
                sta.pop();
                res.push_back(node->val);
            }
        }

        return res;
    }
};

           if(node)を変更し、中央の親ノードを押して、テンプレートの下で中間次の走査を取得します。具体的な手順は次のとおりです。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode* node;
        sta.push(root);
        while (!sta.empty()) {
            node = sta.top();
            sta.pop();
            if (node) {
                if (node->right)
                    sta.push(node->right);
                sta.push(node);           //中间压入父节点
                sta.push(NULL);
                if (node->left)
                    sta.push(node->left);
            } else {
                node = sta.top();
                sta.pop();
                res.push_back(node->val);
            }
        }

        return res;
    }
};

94.二分木の順序通りの走査

トピック:

二分木が与えられた場合、その中次 走査を返します。

解決策1:再帰

class Solution {
private:
    void inorderRes(TreeNode *root, vector<int> &res) {
        if (NULL == root)
            return;
        
        if (root->left)
            inorderRes(root->left, res);

        res.push_back(root->val);

        if (root->right)
            inorderRes(root->right, res);
    }
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;

        inorderRes(root, res);

        return res;
    }
};

解決策2:nullポインターを使用して親ノードをマークします

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

        return res;
    }
};

解決策3:スタックを使用して、ルートから常に右側のサブツリーをプッシュし、出力を中間の順序でトラバースします

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if (NULL == root)
            return res;
        
        stack<TreeNode*> sta;
        TreeNode *node = root;
        while (node || !sta.empty()) {
            while (node) {
                sta.push(node);
                node = node->left;
            }

            node = sta.top();
            sta.pop();
            res.push_back(node->val);

            node = node->right;
        }

        return res;
    }
};

 

おすすめ

転載: blog.csdn.net/sy_123a/article/details/107108532