二叉树的遍历

边学边记】之二叉树的遍历
定义:二叉树遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。
遍历方式:从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
⑴访问结点本身(N),

⑵遍历该结点的左子树(L),

⑶遍历该结点的右子树(R)。

以上三种操作有六种执行次序:

NLR、LNR、LRN、NRL、RNL、RLN。

注意: 前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。
NLR:前序遍历(PreorderTraversal亦称(先序遍历))
若二叉树非空,则依次执行如下操作:

⑴ 访问根结点;

⑵ 遍历左子树;

⑶ 遍历右子树。

LNR:中序遍历(InorderTraversal)
若二叉树非空,则依次执行如下操作:

⑴遍历左子树;

⑵访问根结点;

⑶遍历右子树。

LRN:后序遍历(PostorderTraversal)
若二叉树非空,则依次执行如下操作:

⑴遍历左子树;

⑵遍历右子树;

⑶访问根结点。

层序遍历
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

例子
前序遍历:abdefgc
中序遍历:debgfac
后序遍历:edgfbca
层序遍历:abcdfeg

代码实现
前序遍历:

//递归先序遍历
void PreOrder(Tree t)
{
    if ( t )
    {
    printf("%c",t->data);
    PreOrder(t->lchild);
    PreOrder(t->rchild);
    }
}
//非递归先序遍历
void PreOrder1(Tree t)
{
    Tree p = t;
    Sqstack s;
    InitStack(s);

    while ( p || !StackEmpty(s) )
    {
    if ( p )
    {
        printf("%c",p->data);
        Push(s,p);
        p = p->lchild;    
    }
    else
    {
        Pop(s,p); 
        p = p->rchild;
    }
    }

}

中序遍历


//递归中序遍历
void InOrder(Tree t)
{
    if ( t )
    {
    InOrder(t->lchild);
    printf("%c",t->data);
    InOrder(t->rchild);
    }
}


//非递归中序遍历
void InOrder1(Tree t)
{
    Tree p = t;
    Sqstack s;
    InitStack(s);  

    while ( p || !StackEmpty(s) )
    {
    if ( p )
        {
        Push(s,p);
        p = p->lchild;
    }    
    else
    {
        Pop(s,p);
        printf("%c",p->data);
        p = p->rchild;
    } 
    }
}

后序遍历


//递归后序遍历
void PostOrder(Tree t)
{
    if ( t )
    {
    PostOrder(t->lchild);
     PostOrder(t->rchild);
    printf("%c",t->data);
    }
}


//非递归后序遍历
void PostOrder1(Tree t)
{
    t->isOut = 0;
    Tree p = t;
    Sqstack s;
    InitStack(s); 

    while ( p || !StackEmpty(s) )
    {
    if ( p )
        {
        if ( p->isOut )
            {//左右子树都已输出,则该节点也输出        
            Pop(s,p);
            printf("%c",p->data);
        if (!StackEmpty(s))
                GetTop(s,p); //得到弹出节点元素的父节点
            else
            p = NULL;
        }
        else
        {    
            if ( (p->lchild) && (p->lchild->isOut == 1) )
            {//如果存在左子树,并且左子树已经遍历完,则说明该节点已经入栈,不用再次Push,直接走向右子树          
            p->isOut = 1;
            p = p->rchild;   
              }
            else
            {
            Push(s,p);
            p = p->lchild;
            }          
        }
        }
        else
        {
        if (!StackEmpty(s))
            GetTop(s,p); 
        else
        p = NULL;

        if ( p->rchild )
        {
            p = p->rchild;
        }
        else
        {
           Pop(s,p);
            printf("%c",p->data);
            p->isOut = 1;
            if (!StackEmpty(s))
            {
            GetTop(s,p);
            if ( p->lchild == NULL )
                p->isOut = 1; //右子树已输出,将父节点isOut置1
        }
            else
            p = NULL;
        }

        }
    }

}

分层遍历

void LevelTraverse(BinaryTreeNode * pRoot)
{
    if(pRoot == NULL)
        return NULL;
    queue<BinaryTreeNode *> q;
    q.push(pRoot);
    while(!q.empty())
    {
        BinaryTreeNode * pNode = q.front();
        q.pop();
        Visit(pNode); // 访问节点
        if(pNode->m_pLeft != NULL)
            q.push(pNode->m_pLeft);
        if(pNode->m_pRight != NULL)
            q.push(pNode->m_pRight);
    }
    return;
}

本文代码参考:http://blog.csdn.net/cqnuztq/article/details/8896953
代码部分原文更详细.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值