二叉树的非递归遍历

二叉树定义的数据结构

typedef struct BiNode
{
      char data;   //此处,二叉树中节点值类型为字符型
      struct BiNode *lchild,*rchild;     //左右孩子节点
}BiNode,*BiTree;

二叉树的创建

先申请根节点的空间,然后赋值,然后分别递归建立其左子树和右子树,按照先序序列输入构建一棵二叉树

//按照先序序列输入构建一棵二叉树
void Create(BiTree &T)
{
    char ch;
    scanf("%c",&ch);
    if( '#' == ch )
    {
        T = NULL;
    }
    else
    {
        T=(BiNode *)malloc(sizeof(BiNode));
        T->data=ch;
        Create(T->lchild);
        Create(T->rchild);
    }
}

非递归的先序遍历(栈)

设置一个存放结点指针的栈 S ,从根结点开始,每访问一结点后,按先序规则走左子树,若右子树存在,则将右子树指针进栈,以便以后能正确地返回到该右子树上进行遍历访问。

void PreTraverse(BiTree T)
{
     BiNode *p;
     Stack S;
     S=InitStack();
      if (T)
     {
           Push(S,T);  // 根结点指针进栈
            while (!StackEmpty(S))
           {
                p=Pop(S);  // 出栈,栈顶元素赋给 p
                 while (p)
                {
                     printf( "%c\t" ,p->data);  // 访问 p结点
                      if (p->rchild)
                           Push(S,p->rchild);  // 右子树存在时,进栈
                     p=p->lchild;            // 继续沿着左子树往下走
                }
           }
     }
}

说明:内部循环是从 p 结点出发一直走到最左,走的过程中保存了每一个右子树的地址(因为右子树还没有被访问),而且是先进后出的,即先保存的比后保存的更先被用作返回地址,所以是用栈。外循环正好是当内部循环不下去的时候,退一栈的情形。即换成他的右子树。

非递归的中序遍历(栈)

同前序遍历 ,栈S 存放结点指针。对每棵子树 ( 开始是整棵二叉树 ),沿左找到该子树在中序下的第一结点( 但寻找路径上的每个结点指针要进栈 ),访问之;然后遍历该结点的右子树 ,又寻找该子树在中序下的第一结点,直到栈S 空为止。

void InTraverse(BiTree T)
{
     BiNode *p;
     Stack S;
     S=InitStack();
     Push(S,T);  // 根结点指针进栈
      while (!StackEmpty(S))
     {
            while ((p=GetsTop(S))&&p)  //取栈顶元素且存在,赋给 p
                Push(S,p->lchild);    //p 的左子树进栈
           p=Pop(S);               // 去掉最后的空指针
            if (!StackEmpty(S))
           {
                p=Pop(S);       // 弹出栈顶元素,赋给 p
                printf( "%c\t" ,p->data);   // 访问 p结点
                Push(S,p->rchild);     // 右子树进栈,然后遍历右子树
           }
     }
}

说明:和前序不一样,这里的栈保存的是根结点的地址,因为中序遍历先访问左子树,而根结点没有被访问到。而前序遍历不一样,他一开始就访问根结点,所以他不保存根结点的地址而是保存右子树的地址,因为右子树还没有被访问。总之,用栈就是为了帮我们保存还没有被访问的地址,以便将来我们能找到返回的地址。

非递归的后序遍历(栈)

对一个结点是否能访问,要看他的左、右子树是否遍历完,所以每一个结点对应一个标志位 -tag 。tag=0 ,表示该结点暂不能访问; tag=1 ,表示该结点可以访问。其实是区分这次返回是遍历完左子树返回的还是遍历完右子树返回的,如果是左子树返回的那么就不能访问根结点, 如果是右子树返回的就能访问根结点。当搜索到某 P 结点时,先要遍历其左子树,因而将结点地址 P 及tag=0 进栈;当P 结点的左子树遍历完之后,再遍历其右子树,又将地址 P 及tag=1 进栈;当 P结点右子树遍历完之后( tag=1 ),便可对 P结点进行访问 

void PostTraverse(BiTree T)
{
      int tag;
     BiNode *p;
     Stacks S;
     SNode sdata;
     S=InitStacks();
     p=T;
      while (p||!StacksEmpty(S))
     {
            while (p)
           {
                sdata.q=p;
                sdata.tag=0;
                Pushs(S,&sdata);   //(p,0) 进栈
                p=p->lchild;      // 遍历p 之左子树
           }
           sdata=*Pops(S);  // 退栈
           p=sdata.q;     // 取指针
           tag=sdata.tag; // 状态位
            if (tag==0)     //从左子树返回时,根的 tag=0
           {
                sdata.q=p;
                sdata.tag=1;      // 这时要进入根的右子树了,所以根的 tag=1 ,下次碰到根时就可以访问了
                Pushs(S,&sdata);   //(p,1) 进栈,根还得进一次栈
                p=p->rchild;     // 遍历右子树
           }
            else           //tag=1,这是说明了右子树访问完了返回,所以这次要对根进行访问了
           {
                printf( "%c\t" ,p->data);
                p=NULL;
           }
     }
}

层序遍历(队列)

// 二叉树的层次遍历
void LevelTraverse(BiTree T)
{
     BiNode *p;
     LinkQueue *Q;
     InitQueue(Q);
     EnQueue(Q,T);
      while (!QueueEmpty(Q))
     {
           p=DeQueue(Q);
           printf( "%c\t" ,p->data);
            if (p->lchild!=NULL)
                EnQueue(Q,p->lchild);
            if (p->rchild!=NULL)
                EnQueue(Q,p->rchild);
     }
}

转载自:https://www.cnblogs.com/pkg313133/p/3459171.html


Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值