二叉树非递归遍历

 

      最近一段时间学习数据结构,关于二叉树的遍历,递归遍历很简单,非递归遍历方法不一这里分析一下三种非递归遍历方法的实现

首先定义二叉树结点数据结构:

复制代码
typedef struct btnode *btlink
struct btnode
{
    TreeItem element;
    btlink left; //左子树
    btlink right; //右子树
}Btnode; 
复制代码

 下面给出几种非递归遍历的方法:

 

一:非递归前序遍历:

复制代码
void PreOrder(void (*visit)(btlink u),btlink t)
{
    Stack s = StackInit();
    Push(t,s);
    while(!StackEmpty(s))
    {
        (*visit)(t = Pop(s));
        if(t->right) Push(t->right,s);
        if(t->left) Push(t->left,s);
    }
复制代码

      分析代码,实现方法很简单:

      1:首先将根结点压入栈中,然后根据栈是否为空来进行循环,每次访问一个结点

      2:然后将其存在的左右子结点压入栈中

      3:然后开始从1到3的循环

 

二:非递归中序遍历:

复制代码
void InOrder(void (*visit)(btlink u),btlink t)
{
    Stack s = StackInit();
    btlink tmp = t;
    while( !StackEmpty(s)||tmp)
    {
        while(tmp->left)
        {
            Push(tmp,s);
            tmp = tmp->left;
        }
        if(tmp)
            (*visit)tmp;
     if(!StackEmpty(s)&&!tmp->right)
        {
            tmp = Pop(s);
            (*visit)tmp;
        }
        tmp = tmp->right;
    }
}
复制代码

  分析代码:

     1:首先利用while循环,从根结点开始,如果一个结点没有左子结点,则将这个结点压入

     2:判断临时结点指针是否为空,不为空,则读取该结点

     3:判断栈是否为空,不为空且临时指针右儿子结点为空,则压出一个结点,并读取

     4:临时指针指向其右儿子结点

 

三:非递归后序遍历 

复制代码
void PostOrder(void (*visit)(btlink u),btlink t)
{
    Stack s = StackInit();
    btlink tmp = t;
    btlink tmpvisit;
    while( !StackEmpty(s)||tmp)
    {
        while(tmp->left)
        {
            Push(tmp,s);
            tmp = tmp->left;
        }
        if(tmp->right)
        {
            Push(tmp,s)
            tmp = tmp->right;
        }
        else
        {
            (*visit)tmp;
            tmpvisit = tmp;
            tmp = Pop(s);
            if(tmp->right==tmpvisit||(!tmp->right&&tmp->left==tmpvisit))
            {
                (*visit)tmp;
                tmpvisit =tmp; 
                tmp = Pop(s);
            }
            else if (tmp->right)
            {
                Push(tmp,s);
                tmp = tmp->right;
            }
            else 
            {
                (*visit)tmp;
                tmpvisit = tmp;
                tmp = Pop(s);
            }
        }
        while((tmp->right==tmpvisit||(!tmp->right&&tmp->left==tmpvisit)
        {
            (*visit)tmp;
            tmpvisit==tmp;
            if(!StackEmpty(s))
            {
                tmp = Pop(s);
                if(tmp==t&&tmp->right)
                {
                    Push(t,s);
                    tmp = tmp->right;
                }
            }
            else
                tmp = NULL;
        }
    }
}
复制代码

 

  分析代码:虽然代码比较复杂,但总的来说是自己的一个思路,往各位指正
  1:首先利用while循环,从根结点开始,倘若该结点有右子结点,则压入栈中,若没有,赋予tmp

  2:分析tmp指向的结点,倘若存在右子结点,则将该结点压入栈中,tmp指向其右子结点,倘若没有,则将该结点读取,将读取的结点赋予tmpvisit。

  3:然后进行出栈操作,将出栈的结点赋予tmp,对tmp进行判断,倘若该结点的右子结点已经读取或者右子结点不存在且左子结点已经读取,则读取该结点。否则判断其右子结点是否存在,存在则重复上面2的操作,不存在,则读取该结点,并压出栈,存入tmp中

  4:利用对tmp进行判断,让若其右子结点已经读取或者右子结点不存在且左子结点已经读取,则读取该结点,否则不操作,同时,对栈进行空判断,而且对根结点进行右子结点判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值