二叉树的前序、中序、后续遍历

本篇博文用来介绍二叉树的前序、中序、后续遍历。先通过递归实现三种方式的遍历,再讨论如何采用非递归的方法实现要求。
二叉树的遍历:就是按一定的顺序对每一个结点进行操作,具体操作视情况而定,主要是经过每个结点。
前序:先根结点,再左子树,最后右子树。
中序:先左子树、再根结点、最后右子树。
后序:先左子树、再根结点、最后右子树。

1、递归方法实现三种不同方式的遍历。

前序遍历:

void PreOrderTraverse(BiTree root)            //前序遍历二叉树(递归)
{
    if (root)
    {
        cout << root->data;                   //输出根节点的值
        PreOrderTraverse(root->lchild);       //前序遍历左子树
        PreOrderTraverse(root->rchild);       //前序遍历右子树
    }
}

中序遍历:

void InOrderTraverse(BiTree root)             //中序遍历二叉树
{
    if (root)
    {
        InOrderTraverse(root->lchild);        //中序遍历左子树
        cout << root->data;                   //输出根节点的值
        InOrderTraverse(root->rchild);        //中序遍历右子树
    }
}

后序遍历:

void PostOrderTraverse(BiTree root)           //后序遍历二叉树
{
    if (root)
    {
        PostOrderTraverse(root->lchild);      //后序遍历左子树
        PostOrderTraverse(root->rchild);      //后序遍历右子树
        cout << root->data;                   //输出根节点的值
    }
}

2、非递归实现

中序遍历:
先遍历左子树,在这过程,将经过的结点存入堆栈中,直到空结点;这是弹出一个结点,然后输出,再遍历结点的右子树。

void InOrderTraverse1(BiTree root)
{ //非递归中序遍历二叉树
    if (root == NULL)
    {
        cout << "空二叉树" << endl;
        return;
    }
    stack<BTNode *> s;            //用来存放结点指针的栈
    BTNode * p;
    p = root;
    while (p || !s.empty())
    {
        while (p) //遍历左子树
        {
            s.push(p);//入栈
            p = p->lchild;
        }
        //p为空
        p = s.top();  //获取栈顶元素
        s.pop();
        cout << p->data;           //访问根节点
        p = p->rchild;             //遍历右子树,当做一个新的树,重新进行while(p||!s.empty())
    }
    return ;
}

后序遍历:
方法1:

void PostOrderTraverse2(BiTree root)
{  //后序遍历二叉树(非递归)
    if (root == NULL)
    {
        cout << "空二叉树" << endl;
        return;
    }
    enum Tag{left,right};
    struct snode
    {
        BTNode *p;
        Tag tag;
    }temp;
    stack<snode> s;
    BTNode *p=root;
    while (p || !s.empty())
    {
        while (p)                  //遍历左子树
        {
            temp.p = p;            //根结点第一次被碰到
            temp.tag = Tag::left;
            s.push(temp);
            p = p->lchild;
        }
        temp = s.top();
        s.pop();
        if (temp.tag == Tag::left)  //再次碰到根结点,判断根节点的右子树有没有被访问,依此决定是否访问根结点
        {//不访问根节点
            temp.tag = Tag::right;
            s.push(temp);
            p = temp.p->rchild;    //遍历右子树
        }
        else 
        {
            cout << temp.p->data;
            p = NULL;
        }
    }
    return;
}

方法2:

猜你喜欢

转载自blog.csdn.net/ssf_cxdm/article/details/81390930