Chuyển Đổi Cây Nhị Phân Thành Các Dãy Duyệt: Đệ Quy và Lặp

Dưới đây là triển khai đầy đủ ba kiểu duyệt cây nhị phân — tiền thứ tự (preorder), trung thứ tự (inorder), hậu thứ tự (postorder) — bằng cả hai phương pháp: đệ quy và không đệ quy (dùng ngăn xếp). Mỗi hàm ghi nhận giá trị nút theo thứ tự tương ứng vào một vector đã cho.

Phiên bản đệ quy

struct TreeNode {
    int data;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : data(x), left(nullptr), right(nullptr) {}
};

class BinaryTreeTraversal {
public:
    void preorderRecursive(TreeNode* node, std::vector<int>& result) {
        if (!node) return;
        result.push_back(node->data);
        preorderRecursive(node->left, result);
        preorderRecursive(node->right, result);
    }

    void inorderRecursive(TreeNode* node, std::vector<int>& result) {
        if (!node) return;
        inorderRecursive(node->left, result);
        result.push_back(node->data);
        inorderRecursive(node->right, result);
    }

    void postorderRecursive(TreeNode* node, std::vector<int>& result) {
        if (!node) return;
        postorderRecursive(node->left, result);
        postorderRecursive(node->right, result);
        result.push_back(node->data);
    }

    std::vector<std::vector<int>> getAllSequencesRecursive(TreeNode* root) {
        std::vector<std::vector<int>> output;
        std::vector<int> pre, in, post;

        preorderRecursive(root, pre);
        inorderRecursive(root, in);
        postorderRecursive(root, post);

        output.push_back(pre);
        output.push_back(in);
        output.push_back(post);
        return output;
    }
};

Phiên bản lặp (không đệ quy)

Đối với duyệt hậu thứ tự, thay vì dùng hai ngăn xếp hoặc đánh dấu nút đã thăm, ta tận dụng tính chất: hậu thứ tự (left → right → root) là đảo ngược của duyệt phải-trái-gốc (root → right → left). Do đó, ta thực hiện duyệt "phải-trái-gốc" (giống tiền thứ tự nhưng ưu tiên nhánh phải), rồi lật mảng kết quả.

class BinaryTreeTraversal {
public:
    void preorderIterative(TreeNode* root, std::vector<int>& result) {
        if (!root) return;
        std::stack<TreeNode*> stack;
        stack.push(root);

        while (!stack.empty()) {
            TreeNode* current = stack.top();
            stack.pop();
            result.push_back(current->data);
            if (current->right) stack.push(current->right);
            if (current->left)  stack.push(current->left);
        }
    }

    void inorderIterative(TreeNode* root, std::vector<int>& result) {
        std::stack<TreeNode*> stack;
        TreeNode* curr = root;

        while (curr || !stack.empty()) {
            while (curr) {
                stack.push(curr);
                curr = curr->left;
            }
            curr = stack.top();
            stack.pop();
            result.push_back(curr->data);
            curr = curr->right;
        }
    }

    void postorderIterative(TreeNode* root, std::vector<int>& result) {
        if (!root) return;
        std::stack<TreeNode*> stack;
        TreeNode* curr = root;

        while (curr || !stack.empty()) {
            while (curr) {
                result.push_back(curr->data);
                stack.push(curr);
                curr = curr->right; // ưu tiên nhánh phải
            }
            curr = stack.top();
            stack.pop();
            curr = curr->left;
        }
        std::reverse(result.begin(), result.end());
    }

    std::vector<std::vector<int>> getAllSequencesIterative(TreeNode* root) {
        std::vector<std::vector<int>> output;
        std::vector<int> pre, in, post;

        preorderIterative(root, pre);
        inorderIterative(root, in);
        postorderIterative(root, post);

        output.push_back(pre);
        output.push_back(in);
        output.push_back(post);
        return output;
    }
};

Thẻ: C++17 binary-tree Stack tree-traversal

Đăng vào ngày 16 tháng 10 lúc 11:09