首页 > 代码库 > 二叉树的前中后序遍历迭代&广度遍历

二叉树的前中后序遍历迭代&广度遍历

递归很是简单 但也应该掌握其迭代方式的遍历方法 

这三种的迭代遍历方法需要通过栈来存储节点 尤其是后序遍历还需要 记录当前节点的右子树是否已被遍历 决定是否遍历当前节点

而其广度遍历 只需要一个队列来顺序记录遍历节点 即可轻松解决问题  主要思想在程序代码中来做说明

 

前序遍历:遍历结果返回一个vector容器中

std::vector<int> BinaryTree::pre_order_iter(Binary_node *root)
{
    std::vector<int> res; 
    std::stack<Binary_node*> stack_bn;
    Binary_node *p_top = nullptr;
    stack_bn.push(root); //从根节点开始将节点入栈
    while (!stack_bn.empty())
    {
        p_top = stack_bn.top();
        while (p_top)  //前序遍历中 首先遍历父节点 所以在此循环中先从根节点开始遍历栈中节点  向左走到尽头
        {
            res.push_back(p_top->val);
            stack_bn.push(p_top->left);  // 一边入栈 一边遍历
            p_top = stack_bn.top();
        }
        stack_bn.pop();  //一当前节点的左子树为空 首先弹出空的左子树
        if (!stack_bn.empty())
        {
            p_top = stack_bn.top();
            stack_bn.pop();     //然后弹出当前节点 因为已经被遍历过了
            stack_bn.push(p_top->right); //然后向右走一步 下次循环自此开始 向左到尽头
        }
    }
    return res;
}

 

前序遍历:遍历结果返回一个vector容器中
std::vector<int> BinaryTree::in_order_iter(Binary_node *root)
{
    std::vector<int> res;
    std::stack<Binary_node*> stack_bn;
    Binary_node *p_top = nullptr;
    stack_bn.push(root);
    while (!stack_bn.empty())
    {
        p_top = stack_bn.top();
        while (p_top)  //与前序遍历有像似之处  先往左走到尽头 压入栈中
        {
            stack_bn.push(p_top->left);
            p_top = stack_bn.top();
        }
        stack_bn.pop();  //弹出最下层的空节点
        if (!stack_bn.empty())
        {
            p_top = stack_bn.top();
            stack_bn.pop();
            res.push_back(p_top->val);  //弹出并遍历最左的节点
            stack_bn.push(p_top->right);// 往已弹出的遍历节点的右走一步
        }
    }

    return res;
}

 

//后序遍历 需要记录当前节点和其右节点是否已被遍历的信息 所以定义了如下数据结构
struct snode
{
    Binary_node *node;
    bool right_visited;
    snode(Binary_node* p, bool vis) :node(p), right_visited(vis){}
    snode() :node(&Binary_node()){}
};
std::vector<int> BinaryTree::post_order_iter(Binary_node *root)
{
    std::vector<int> res;
    std::stack<snode> stack_sn;//本次栈中需要存放新定义的节点
    snode *p_top;
    Binary_node *temp = root;
    while (temp)
    {
        stack_sn.push(snode(temp, false));//从根节点开始一直往左 全部压入栈中
        temp = temp->left;
    }
    while (!stack_sn.empty())
    {
        p_top = &(stack_sn.top()); //对于栈顶元素 如果其没有右节点或者右节点已经遍历 则遍历当前节点 并弹出栈后退一步
        if (!p_top->node->right || p_top->right_visited)
        {
            stack_sn.pop();
            res.push_back(p_top->node->val);
        }
        else//否则 需要遍历其右子树部分 首先需要设置其右子树被遍历的标记
        {
            p_top->right_visited = true;
            temp = p_top->node->right;
            while (temp)        //然后往左下方走到尽头 压入栈中
            {
                stack_sn.push(snode(temp, false));
                temp = temp->left;
            }
        }
    }


    return res;
}


//广度遍历 如前所述  通过一个队列来依次存储相应节点 完成遍历
std::vector<int> BinaryTree::level_trave(Binary_node *root)
{
    std::vector<int> res;
    std::queue<Binary_node*> que;
    Binary_node *p_front;
    que.push(root);
    while (!que.empty())
    {
        p_front = que.front();
        que.pop();
        res.push_back(p_front->val);

        if (p_front->left)
            que.push(p_front->left);
        if (p_front->right)
            que.push(p_front->right);
    }
    return res;
}

二叉树的前中后序遍历迭代&广度遍历