剑指offer面试题-二叉树的前序中序后序遍历

  • 题目
    传入一个树的根节点,分别采用非递归实现树的前序,中序,后序遍历。节点定义如下。
struct BinaryTreeNode
{   
    BinaryTreeNode(char data)
    :_pLeftChild(NULL)
    , _pRightChild(NULL)
    , _data(data)
    {}
    BinaryTreeNode *_pLeftChild;
    BinaryTreeNode *_pRightChild;
    char _data;
};

创建树的代码

void _CreateBinaryTree(BinaryTreeNode *&pRoot, char *pStr, size_t size, size_t& index)
{//此处index一定要用引用
    if (index < size && '#' != pStr[index])
    {
        pRoot = new  BinaryTreeNode(pStr[index]);
        _CreateBinaryTree(pRoot->_pLeftChild, pStr, size, ++index);
        _CreateBinaryTree(pRoot->_pRightChild, pStr, size, ++index);
    }
}
  • 前序遍历

  • 实现思路

采用栈实现,首先将根入栈
栈不为空循环
取栈顶元素访问,出栈
右孩子不为空右孩子入栈
左孩子不为空左孩子入栈

  • 实现代码
void PreOrder(BinaryTreeNode *pRoot)
{
    if (NULL == pRoot)
        return;
    stack<BinaryTreeNode *> s;
    s.push(pRoot);
    while (!s.empty())
    {
        BinaryTreeNode *top = s.top();
        cout << top->_data;
        s.pop();
        if (top->_pRightChild)
            s.push(top->_pRightChild);
        if (top->_pLeftChild)
            s.push(top->_pLeftChild);   
    }
}

测试用例:

void testpre()
{
    BinaryTreeNode *pRoot;
    char *str = "abcd"; // 左单支
    size_t size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    PreOrder(pRoot);
    cout << endl;
    str = "a#b#c#d";//右单支
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    PreOrder(pRoot);
    cout << endl;
    str = "ab#df##g##ce#h";//普通树
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    PreOrder(pRoot);
    PreOrder(NULL);
}
  • 中序遍历
  • 实现思路

定义一个结点从根开始寻找最左边的结点
栈不为空,且结点不为空循环
寻找最左边节点,并将沿途结点入栈
访问栈顶元素,出栈
如果有右孩子,将右孩子赋给定义 的结点。

  • 实现代码
void Inorder(BinaryTreeNode *pRoot)
{
    if (NULL == pRoot)
        return;
    stack<BinaryTreeNode *> s;
    BinaryTreeNode *pCur = pRoot;
    while (!s.empty() || pCur)
    {
        while (pCur)
        {
            s.push(pCur);
            pCur = pCur->_pLeftChild;//寻找最左边的结点
        }
        BinaryTreeNode *top = s.top();
        cout << top->_data;
        s.pop();
        pCur = top->_pRightChild;
    }
}
  • 测试用例
void testin()
{
    BinaryTreeNode *pRoot;
    char *str = "abcd"; // 左单支//dcba
    size_t size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    Inorder(pRoot);
    cout << endl;
    str = "a#b#c#d";//右单支//abcd
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    Inorder(pRoot);
    cout << endl;
    str = "ab#df##g##ce#h";//普通树//bfdgaehc
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    Inorder(pRoot);
    Inorder(NULL);
}
  • 后序遍历

  • 实现思路

定义一个结点pCur寻找最左边的结点,定义一个pPre保存前一个访问节点。
栈不为空或者pCur不为空循环
寻找 最左边的结点,并将沿途结点入栈
如果栈顶元素没有右孩子,或者右孩子刚刚被访问过,访问栈顶元素,并弹出
有右孩子将右孩子赋值给pCur循环继续

void postorder(BinaryTreeNode *pRoot)
{
    if (NULL == pRoot)
        return;
    stack<BinaryTreeNode *> s;
    BinaryTreeNode *pCur = pRoot;
    BinaryTreeNode *pPre = NULL;
    while (!s.empty() || pCur)
    {
        while (pCur)
        {
            s.push(pCur);
            pCur = pCur->_pLeftChild;
        }
        BinaryTreeNode *top = s.top();
        if (NULL == top->_pRightChild || pPre == top->_pRightChild)
        {
            cout << top->_data << " ";
            pPre = top;
            s.pop();
        }
        else
            pCur = top->_pRightChild;
    }
}

测试用例

void testpost()
{
    BinaryTreeNode *pRoot;
    char *str = "abcd"; // 左单支//dcba
    size_t size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    postorder(pRoot);
    cout << endl;
    str = "a#b#c#d";//右单支//dcba
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    postorder(pRoot);
    cout << endl;
    str = "ab#df##g##ce#h";//普通树//
    size = 0;
    _CreateBinaryTree(pRoot, str, strlen(str), size);
    postorder(pRoot);
    postorder(NULL);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值