c++n叉树后序遍历

48 阅读2分钟

在C++中,对n叉树(也叫n叉树、多叉树)进行后序遍历,通常有两种常见的方法实现:递归方法和迭代方法。

  1. 递归方法

递归方法是最直观的,它通过递归调用自身来访问每个节点的子节点。

首先,定义n叉树的节点结构:

#include <iostream>
#include <vector>
 
class Node {
public:
    int val;
    std::vector<Node*> children;
 
    Node() {}
 
    Node(int _val) {
        val = _val;
    }
 
    Node(int _val, std::vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};

然后,实现后序遍历的递归函数:

void postorder(Node* root) {
    if (root == nullptr) return;
    for (Node* child : root->children) {
        postorder(child); // 先遍历所有子节点
    }
    std::cout << root->val << " "; // 然后访问根节点
}  
  1. 迭代方法

迭代方法通常使用栈来实现,因为它可以避免递归可能带来的栈溢出问题。

首先,定义一个辅助结构来存储节点和访问状态(是否已访问子节点):

struct TreeNodeInfo {
    Node* node;
    bool visitedChildren; // 是否已访问子节点
};

然后,实现后序遍历的迭代函数:

void postorderIterative(Node* root) {
    if (root == nullptr) return;
    std::stack<TreeNodeInfo> stack;
    stack.push({root, false}); // 根节点入栈,子节点未访问
    while (!stack.empty()) {
        TreeNodeInfo top = stack.top();
        if (!top.visitedChildren) { // 如果未访问子节点,先访问子节点
            for (Node* child : top.node->children) { // 反向遍历可以保证左子树先被访问(但不是必须的)
                stack.push({child, false}); // 子节点入栈,子节点未访问状态
            }
            stack.top().visitedChildren = true; // 标记当前节点子节点已访问
        } else { // 如果已访问子节点,访问当前节点并弹出栈
            std::cout << top.node->val << " "; // 访问当前节点值
            stack.pop(); // 弹出当前节点信息
        }
    }
}  

使用示例:

int main() {
    // 构建一个简单的n叉树进行测试
    Node* root = new Node(1);
    root->children.push_back(new Node(3));
    root->children.push_back(new Node(2));
    root->children.push_back(new Node(4));
    root->children[0]->children.push_back(new Node(5));
    root->children[0]->children.push_back(new Node(6));
    // 使用递归方法进行后序遍历:
    std::cout << "Postorder (recursive): ";
    postorder(root); // 应输出:5 6 3 4 2 1 
    std::cout << std::endl;
    // 使用迭代方法进行后序遍历:
    std::cout << "Postorder (iterative): ";
    postorderIterative(root); // 应输出:5 6 3 4 2 1 
    std::cout << std::endl;
    return 0;
}

这样,你就可以在后序遍历n叉树时选择使用递归或迭代方法了。