zoukankan      html  css  js  c++  java
  • 二叉树的先序,中序,后序,层次的递归及非递归遍历

    昨天写数据结构关于二叉树的几种顺序的递归及非递归遍历的程序,后续遍历有点难。现在把程序给大家参考一下,有些思路参考自:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html的思路。

    一、先序遍历二叉树

       1.递归遍历

        每次先判断是否为空树,若不是则访问根节点,然后左子树,最后右子树。

    void PreOrderTraverse1(BiTree T)
    {//先序遍历二叉树T的递归算法
    // cout<<"二叉树先序递归遍历 ";
    if(T) //若二叉树非空
    {
    cout<<T->data; //访问根节点
    PreOrderTraverse1(T->lchild); //遍历左孩子
    PreOrderTraverse1(T->rchild); //遍历右孩子
    }

    }

    复制代码

      2.非递归遍历

       判断栈是否为空或子树为空,若不为空,就访问左孩子入栈,直至左孩子为空,若左孩子为空,就出栈,然后访问右孩子,入栈,就这样不断的循环。

    复制代码

    void PreOrderTraverse2(BiTNode *T)
    {//先序遍历二叉树T的非递归算法
    // cout<<"二叉树先序非递归遍历 ";
    StackNode *S;
    BiTNode *p;
    S=NULL;
    S=InitStack(S);
    p=T;

    // cout<<"pre1.1 ";
    if(p==NULL)
    {
    // cout<<"pre1.2 ";
    cout<<"树为空 ";
    return;
    }
    // cout<<"pre1.3 ";
    while(p||!StackEmpty(S))
    {

    // cout<<"pre1.4 ";
    if(p)
    {
    // cout<<"pre1.5 ";
    Push(S,p);
    cout<<p->data;
    p=p->lchild;
    }
    else
    {
    // cout<<"pre1.6 ";
    Pop(S,p);
    p=p->rchild;
    }
    }
    // cout<<"pre1.7 ";
    }

    复制代码

     

    二、中序遍历二叉树

         1.递归遍历

          每次先判断树是否为空,若不为空,则访问左子树,然后根子树,最后右子树。

    复制代码
    
    

    void InOrderTraverse1(BiTree T)
    {//中序遍历二叉树T的递归算法
    // cout<<"二叉树中序递归遍历 ";
    if(T) //若二叉树非空
    {
    InOrderTraverse1(T->lchild); //遍历左孩子
    cout<<T->data; //访问根节点
    InOrderTraverse1(T->rchild); //遍历右孩子
    }

    
    

    }

    
    
    复制代码

        2.非递归遍历

        思路基本和先序差不多,只是输出数据的时候不一样。判断栈和树是否为空,若不,则判断树是否为空,不为继续将左子树进栈,若为空,则出栈,输出数据,然后访问右子树。

    复制代码
    
    

    void InOrderTraverse2(BiTree &T)
    {//中序遍历二叉树T的非递归算法
    // cout<<"二叉树中序非递归遍历 ";
    StackNode *S;
    BiTNode *p;
    S=InitStack(S);
    p=T;
    while(p||!StackEmpty(S))
    {
    if(p)
    {
    Push(S,p);
    p=p->lchild;
    }
    else
    {
    Pop(S,p);
    cout<<p->data;
    p=p->rchild;
    }
    }
    }

    
    
    复制代码

    三、后序遍历二叉树

        1.递归遍历

        先判断树是否为空,若不为,先左子树,后右子树,然后根节点。

    复制代码
    
    

    void LastOrderTraverse1(BiTree T)
    {//后序遍历二叉树T的递归算法
    // cout<<"二叉树后序递归遍历 ";
    if(T) //若二叉树非空
    {
    LastOrderTraverse1(T->lchild); //遍历左孩子
    LastOrderTraverse1(T->rchild); //遍历右孩子
    cout<<T->data; //访问根节点
    }

    
    

    }

    
    
    复制代码

        2.非递归遍历

         要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

    复制代码
    
    

    void LastOrderTraverse2(BiTNode *T)
    {//后序遍历二叉树T的非递归算法
    // cout<<"二叉树后序非递归遍历 ";
    StackNode *S;
    BiTNode *p,*cur;
    S=InitStack(S);
    p=T;
    p=NULL;cur=NULL;
    Push(S,T);
    while(!StackEmpty(S))
    {
    cur=NULL;
    GetTop(S,cur);
    if((cur->lchild==NULL && cur->rchild==NULL) || (p!=NULL &&(p==cur->lchild || p==cur->rchild)))
    {
    cout<<cur->data;
    p=cur;
    Pop(S,cur);

    }
    else
    {
    if(cur->rchild!=NULL)
    {
    Push(S,cur->rchild);
    }
    if(cur->lchild!=NULL)
    {
    Push(S,cur->lchild);
    }
    }
    }
    }

    
    
    复制代码

     

     

    下面是完整的程序:

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    using namespace std;


    typedef struct BiTNode //树的结点
    {
    char data; //节点数据域
    struct BiTNode *lchild,*rchild; //左右孩子指针
    }BiTNode,*BiTree;

    typedef BiTNode *SElemType;

    typedef struct StackNode //栈的结点
    {
    SElemType data;
    StackNode *next;
    }StackNode;

    StackNode *InitStack(StackNode *S)
    {
    S=(StackNode *)malloc(sizeof(StackNode));
    if(S==NULL)
    {
    cout<<"内存不足,不能分配栈 ";
    exit(0);
    }
    S->next=NULL;
    return(S);
    }

    int StackEmpty(StackNode *S)
    {
    if(S->next==NULL)
    {
    return(1);
    }
    return(0);
    }

    void Push(StackNode *S,SElemType data)
    {
    StackNode *p;
    p = (StackNode *)malloc(sizeof(StackNode));
    if(p==NULL)
    {
    cout<<"内存不足,不能分配栈 ";
    exit(0);
    }
    p->data=data;
    p->next=S->next;
    S->next=p;

    }

    void Pop(StackNode *S,SElemType &data)
    {
    StackNode *p;
    if(S->next==NULL)
    {
    cout<<"栈为空,无返回值 ";
    }
    p=S->next;
    data=p->data;
    S->next=p->next;
    free(p);

    }

    int GetTop(StackNode *S,SElemType &data)
    {
    if(S->next!=NULL)
    {
    data=S->next->data;
    return(1);
    }
    else
    {
    return(0);
    }
    }

     

    BiTNode *InitTree(BiTNode *T)
    {
    char data;
    cin>>data;
    if('#'==data)
    {
    T=NULL;
    }
    else
    {
    T=(BiTNode *)malloc(sizeof(BiTNode));
    T->data=data;
    T->lchild=InitTree(T->lchild);
    T->rchild=InitTree(T->rchild);

    }
    return(T);
    }

    void PreOrderTraverse1(BiTree T)
    {//先序遍历二叉树T的递归算法
    // cout<<"二叉树先序递归遍历 ";
    if(T) //若二叉树非空
    {
    cout<<T->data; //访问根节点
    PreOrderTraverse1(T->lchild); //遍历左孩子
    PreOrderTraverse1(T->rchild); //遍历右孩子
    }

    }

    void InOrderTraverse1(BiTree T)
    {//中序遍历二叉树T的递归算法
    // cout<<"二叉树中序递归遍历 ";
    if(T) //若二叉树非空
    {
    InOrderTraverse1(T->lchild); //遍历左孩子
    cout<<T->data; //访问根节点
    InOrderTraverse1(T->rchild); //遍历右孩子
    }

    }

    void LastOrderTraverse1(BiTree T)
    {//后序遍历二叉树T的递归算法
    // cout<<"二叉树后序递归遍历 ";
    if(T) //若二叉树非空
    {
    LastOrderTraverse1(T->lchild); //遍历左孩子
    LastOrderTraverse1(T->rchild); //遍历右孩子
    cout<<T->data; //访问根节点
    }

    }


    void PreOrderTraverse2(BiTNode *T)
    {//先序遍历二叉树T的非递归算法
    // cout<<"二叉树先序非递归遍历 ";
    StackNode *S;
    BiTNode *p;
    S=NULL;
    S=InitStack(S);
    p=T;

    // cout<<"pre1.1 ";
    if(p==NULL)
    {
    // cout<<"pre1.2 ";
    cout<<"树为空 ";
    return;
    }
    // cout<<"pre1.3 ";
    while(p||!StackEmpty(S))
    {

    // cout<<"pre1.4 ";
    if(p)
    {
    // cout<<"pre1.5 ";
    Push(S,p);
    cout<<p->data;
    p=p->lchild;
    }
    else
    {
    // cout<<"pre1.6 ";
    Pop(S,p);
    p=p->rchild;
    }
    }
    // cout<<"pre1.7 ";
    }

     

    void InOrderTraverse2(BiTree &T)
    {//中序遍历二叉树T的非递归算法
    // cout<<"二叉树中序非递归遍历 ";
    StackNode *S;
    BiTNode *p;
    S=InitStack(S);
    p=T;
    while(p||!StackEmpty(S))
    {
    if(p)
    {
    Push(S,p);
    p=p->lchild;
    }
    else
    {
    Pop(S,p);
    cout<<p->data;
    p=p->rchild;
    }
    }
    }

    void LastOrderTraverse2(BiTNode *T)
    {//后序遍历二叉树T的非递归算法
    // cout<<"二叉树后序非递归遍历 ";
    StackNode *S;
    BiTNode *p,*cur;
    S=InitStack(S);
    p=T;
    p=NULL;cur=NULL;
    Push(S,T);
    while(!StackEmpty(S))
    {
    cur=NULL;
    GetTop(S,cur);
    if((cur->lchild==NULL && cur->rchild==NULL) || (p!=NULL &&(p==cur->lchild || p==cur->rchild)))
    {
    cout<<cur->data;
    p=cur;
    Pop(S,cur);

    }
    else
    {
    if(cur->rchild!=NULL)
    {
    Push(S,cur->rchild);
    }
    if(cur->lchild!=NULL)
    {
    Push(S,cur->lchild);
    }
    }
    }
    }

     

    int main()
    {
    BiTNode *Tree;
    Tree=NULL;
    cout<<"按照层次遍历建立树,'#'表示树为空 " <<endl;
    cout<<"请输入要建立的树:"<<endl;
    cout<<" ";
    Tree=InitTree(Tree);
    int choose;
    cout<<"请输入0(表示递归遍历)或1(表示非递归遍历) ";
    cin>>choose;
    if(choose==0)
    {
    cout<<"二叉树先序递归遍历 ";
    PreOrderTraverse1(Tree);
    cout<<endl;
    cout<<"二叉树中序递归遍历 ";
    InOrderTraverse1(Tree);
    cout<<endl;
    cout<<"二叉树后序递归遍历 ";
    LastOrderTraverse1(Tree);
    cout<<endl;
    }
    else if(choose==1)
    {
    cout<<"二叉树先序非递归遍历 ";
    PreOrderTraverse2(Tree);
    cout<<endl;
    cout<<"二叉树中序非递归遍历 ";
    InOrderTraverse2(Tree);
    cout<<endl;
    cout<<"二叉树后序非递归遍历 ";
    LastOrderTraverse2(Tree);
    cout<<endl;
    }
    else
    {
    cout<<"输入错误 "<<endl;
    }
    return 0;
    }

     

     

     

  • 相关阅读:
    spring MVC 后台token防重复提交解决方案
    redis实现分布式锁
    java spring boot项目部署-上
    倒计数锁存器(CountDown Latch)和 CyclicBarrier(同步屏障)
    通过条件注解@Conditional细粒度的选择bean实例
    Netflix中的负载均衡策略
    C# lambda表达式参数的正确使用姿势
    RabbitMQ如何保证发送端消息的可靠投递-发生镜像队列发生故障转移时
    RabbitMQ如何保证发送端消息的可靠投递
    vue项目目录结构详解
  • 原文地址:https://www.cnblogs.com/xisheng/p/8094289.html
Copyright © 2011-2022 走看看