二叉树的前序/中序/后序遍历方法的递归与循环的实现

对于二叉树的三种遍历方法, 递归方法实现起来简单,明白。可是效率很差,而且不安全,可能会栈溢出。循环的实现,确定是基于栈的数据结构来实现,要复杂一些。代码以下:node

 

前序遍历的实现:

// 前序遍历 ----基于递归
void PreorderTraversal(BinaryTreeNode* pRoot_)
{
    // 为空时,直接返回了
    if (!pRoot_)
        return;

    std::cout << pRoot_->m_nValue << " ";
    PreorderTraversal(pRoot_->m_pLeft);
    PreorderTraversal(pRoot_->m_pRight);
}

// 前序遍历 ----基于循环
void PreorderTraversal_ByCycle(BinaryTreeNode* pRoot_)
{
    // 为空时,直接返回
    if (!pRoot_)
        return;

    // 须要使用到栈数据结构, 先把右子树放到栈中,再把左子树放到栈中
    stack<BinaryTreeNode*> _StackNodes;
    _StackNodes.push(pRoot_);
    while (!_StackNodes.empty())
    {
        BinaryTreeNode* _pCurrentNode = _StackNodes.top();
        _StackNodes.pop();
        std::cout << _pCurrentNode->m_nValue << " ";

        // 把非空的左右子节点放到栈中, 注意:要先放右节点,再放左节点
        BinaryTreeNode* _pRight = _pCurrentNode->m_pRight;
        BinaryTreeNode* _pLeft = _pCurrentNode->m_pLeft;
        if (_pRight)
            _StackNodes.push(_pRight);
        if (_pLeft)
            _StackNodes.push(_pLeft);

    }   
}

 

中序遍历的实现:

// 中序遍历 ---- 基于递归
void InorderTraversal(BinaryTreeNode* pRoot_)
{
    // 为空时,直接返回
    if (!pRoot_)
        return;

    InorderTraversal(pRoot_->m_pLeft);
    std::cout << pRoot_->m_nValue << " ";
    InorderTraversal(pRoot_->m_pRight);
}

// 中序遍历 ---- 基于循环
void InorderTraversal_ByCycle(BinaryTreeNode* pRoot_)
{
    // 为空时,直接返回
    if (!pRoot_)
        return;

    // 初始化一个栈数据结构
    std::stack<BinaryTreeNode*> _StackNodes;

    // 先一股脑地把左子节点放到的栈中, 由于这时栈顶的叶结点就是咱们遍历的起点
    BinaryTreeNode* _pCurrentNode = pRoot_;
    while (_pCurrentNode)
    {
        _StackNodes.push(_pCurrentNode);
        _pCurrentNode = _pCurrentNode->m_pLeft;
    }

    while (!_StackNodes.empty())
    {
        // 遍历栈顶的节点
        BinaryTreeNode* _pCurrentNode = _StackNodes.top();
        _StackNodes.pop();
        std::cout << _pCurrentNode->m_nValue << " ";

        // 即然遍历到了当前的节点,说明了它的左子树已经遍历完了,不须要管了。 咱们如今
        // 须要关注的是:当前节点的右子树是否为空了, 若是不为空,则须要去处理一下了。
        _pCurrentNode = _pCurrentNode->m_pRight;
        while (_pCurrentNode)
        {
            _StackNodes.push(_pCurrentNode);
            _pCurrentNode = _pCurrentNode->m_pLeft;
        }
    }
}

 

后序遍历的实现:

// 后序遍历 ---- 基于递归
void PostorderTraversal(BinaryTreeNode* pRoot_)
{
    // 为空时,直接返回
    if (!pRoot_)
        return;

    PostorderTraversal(pRoot_->m_pLeft);
    PostorderTraversal(pRoot_->m_pRight);
    std::cout << pRoot_->m_nValue << " ";
}

// 后序遍历 ---- 基于循环
void PostorderTraversal_ByCycle(BinaryTreeNode* pRoot_)
{
 // 为空时,直接返回
    if (!pRoot_)
        return;

    // 使用一个栈的数据结构
    std::stack<BinaryTreeNode*> _StackNodes;

    // 把咱们查找第一个应该遍历的node的路径上通过的全部node按顺序一股脑地压入栈中
    BinaryTreeNode* _pCurrentNode = pRoot_;
    while (_pCurrentNode)
    {
        _StackNodes.push(_pCurrentNode);
        // 优先选择不为空的左节点,若是左节点为空,再考虑右节点(右节点为空也没有关系)
        if (_pCurrentNode->m_pLeft)
            _pCurrentNode = _pCurrentNode->m_pLeft;
        else
            _pCurrentNode = _pCurrentNode->m_pRight;
    }

    while (!_StackNodes.empty())
    {
        // 遍历栈顶的节点
        BinaryTreeNode* _pCurrentNode = _StackNodes.top();
        _StackNodes.pop();
        std::cout << _pCurrentNode->m_nValue << " ";

        // 既然遍历到了当前节点,说明它的左子树与右子树都遍历完了,不须要管了。咱们如今
        // 须要关注的是: 若是当前节点为父节点的左节点,则须要判断父节点的右节点是否为空.
        // 若是不为空,则须要去处理父节点的右节点了。
        //
        // 另外,若是当前节点不右父节点的右节点,也不须要管,由于接下来会去遍历父节点。
        if (!_StackNodes.empty() && _pCurrentNode == _StackNodes.top()->m_pLeft)
        {
            _pCurrentNode = _StackNodes.top()->m_pRight;
            while (_pCurrentNode)
            {
                _StackNodes.push(_pCurrentNode);
                // 优先选择左节点,当左节点为空时,再选择右节点(右节点为空,也没事)
                if (_pCurrentNode->m_pLeft)
                    _pCurrentNode = _pCurrentNode->m_pLeft;
                else
                    _pCurrentNode = _pCurrentNode->m_pRight;
            }
        }
    }
}

 

 

最后,补充一个宽度优先遍历的实现,即一层层地遍历:安全

分层遍历:

// 宽度优先遍历,就是一层层地遍历。 这确定是基于单端队列来实现
void BreadthFirstTraversal(BinaryTreeNode* pRoot_)
{
    if (!pRoot_)
        return;

    std::queue<BinaryTreeNode*> _QueueNodes;
    _QueueNodes.push(pRoot_);
    while (!_QueueNodes.empty())
    {
        BinaryTreeNode* _pCurrentNode = _QueueNodes.front();
        _QueueNodes.pop();
        std::cout << _pCurrentNode->m_nValue << " ";

        // 把当前节点的左右非空子节点放入到队列中
        BinaryTreeNode* _pLeft = _pCurrentNode->m_pLeft;
        BinaryTreeNode* _pRight = _pCurrentNode->m_pRight;
        if (_pLeft)
            _QueueNodes.push(_pLeft);
        if (_pRight)
            _QueueNodes.push(_pRight);
    }
}
相关文章
相关标签/搜索