• 记录一下关于二叉树的非递归遍历


    利用栈的非递归先序遍历二叉树:

    额,这个是我自己写的,可能算法有点啰嗦……

    /**********
    【题目】试利用栈及其基本操作写出二叉树T的非递归
    的先序遍历算法。
    二叉链表类型定义:
    typedef struct BiTNode {
      TElemType  data;
      struct BiTNode  *lchild,*rchild;
    } BiTNode, *BiTree;
    可用栈类型Stack的相关定义:
    typedef BiTree SElemType;   // 栈的元素类型
    Status InitStack(Stack &S); 
    Status StackEmpty(Stack S); 
    Status Push(Stack &S, SElemType e);
    Status Pop(Stack &S, SElemType &e); 
    Status GetTop(Stack S, SElemType &e); 
    **********/
    
    /*思路:先访问根节点,然后向左一直走下去,每走一个都是先访问根节点,并沿途把右子树入栈。向左走完后,开始搞栈里面的元素,
    对栈里面的元素,先看它的右子树存不存在,若存在则入栈,然后再对这个元素的右子树也进行向左走操作*/
    
    void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType));
    Stack S; 
    
    void PreOrder(BiTree T, void (*visit)(TElemType))
    /* 使用栈,非递归先序遍历二叉树T,     */
    /* 对每个结点的元素域data调用函数visit */
    {      
        InitStack(S);
        BiTree tree2 = T;
        BiTree treeTemp = tree2;
        while(treeTemp && treeTemp->data!='#') {     //好吧做了后面的题后发现好像可以不用这个data='#',但懒得改了
            visit(treeTemp->data);
            printf("visit the root:%c
    ",treeTemp->data);
            traverseLeft(treeTemp->lchild, S, visit);//遍历左边的节点,并沿途将他们的右子树入栈,遍历后treeTemp指向最左边那个子树              
            while(!StackEmpty(S)) {
                printf("get into the stack
    "); 
                Pop(S, treeTemp);
                visit(treeTemp->data);
                printf("visit the stack of the rchild:%c
    ",treeTemp->data);
                if(treeTemp->rchild && treeTemp->rchild->data!='#') {
                    Push(S, treeTemp->rchild);
                }
                traverseLeft(treeTemp->lchild, S, visit);     
            }
            treeTemp = tree2->rchild;
            tree2 = tree2->rchild;
        }
    }
    
    void traverseLeft(BiTree T, Stack &S, void (*visit)(TElemType)) {
        while(T && T->data!='#') {
            visit(T->data);
            printf("visit the lchild:%c
    ",T->data);
            if(T->rchild && T->data!='#') {
                Push(S, T->rchild);
                if(!StackEmpty(S)) {
                    printf("push %c into the stack
    ",T->rchild->data);
                }               
            }
            T = T->lchild;
        }  
    }

    利用栈实现非递归后序遍历二叉树:

    这个是网上找的实现算法:

    /**********
    【题目】试利用栈及其基本操作写出二叉树T的非递归
    的后序遍历算法(提示:为分辨后序遍历时两次进栈的
    不同返回点,需在指针进栈时同时将一个标志进栈)。
    二叉链表类型定义:
    typedef struct BiTNode {
      TElemType  data;
      struct BiTNode  *lchild,*rchild;
    } BiTNode, *BiTree;
    可用栈类型Stack的相关定义:
    typedef struct {
      struct BiTNode *ptr; // 二叉树结点的指针类型
      int      tag; // 0..1
    } SElemType;    // 栈的元素类型
    Status InitStack(Stack &S); 
    Status StackEmpty(Stack S); 
    Status Push(Stack &S, SElemType e);
    Status Pop(Stack &S, SElemType &e); 
    Status GetTop(Stack S, SElemType &e); 
    **********/
    
    
    
    void PostOrder(BiTree T, void (*visit)(TElemType))
    /* 使用栈,非递归后序遍历二叉树T,     */
    /* 对每个结点的元素域data调用函数visit */
    {
        SElemType a,b; //a可以说是主要遍历这个树的一个指针这样的,b是主要用来处理从栈出来的东西
    
    Stack s; 
    
    a.ptr=T; 
    
    while(a.ptr){ 
    
        if(a.ptr->lchild&&a.ptr->rchild){ //如果有两个孩子的话
    
            a.tag=1; 
    
            Push(s,a); //属于1号
    
            a.ptr=a.ptr->lchild; //走左孩子 
    
        } 
    
        else if(a.ptr->lchild&&!a.ptr->rchild){ //如果只有左孩子的话
    
            a.tag=0; //属于0号
    
            Push(s,a); 
    
            a.ptr=a.ptr->lchild; //走左孩子
    
        } 
    
        else if(!a.ptr->lchild&&a.ptr->rchild){ //如果只有右孩子的话
    
            a.tag=0; //属于0号
    
            Push(s,a); 
    
            a.ptr=a.ptr->rchild; //走右孩子
    
        } 
    
        else if(!a.ptr->lchild&&!a.ptr->rchild) { //如果是叶子结点的话
    
            (*visit)(a.ptr->data); //先访问这个叶子结点
    
            Pop(s,b); //然后就开始访问栈里面的东西了,出栈,用b来装
    
            if(b.tag==1) //如果栈里面迟来的是个有两个孩子的东西,说明刚刚它走的是左孩子,然后现在要走它的右孩子并把它变成tag为0
    
            { 
    
                b.tag=0; 
    
                a.ptr=b.ptr->rchild; //走右孩子
    
                Push(s,b); 
    
            } 
    
            else if(b.tag==0) //如果从栈出来的这个是只有一个孩子的,说明它的孩子已经访问过了,因为栈里的已经是往回走了嘛,它进去的时候如果只有一个孩子,那
                                //回去就说明它的孩子都被访问过了
    
            { 
    
                a=b; //依然用a来走遍历
    
                while(a.tag==0&&!StackEmpty(s)) //如果栈未空且出来的元素都是tag为0的
        
                { 
        
                    (*visit)(a.ptr->data); 
    
                    Pop(s,a); 
    
                } 
    
                if(a.tag==0&&StackEmpty(s)){ //如果栈里面已经没有元素了,就指向NULL,也就是遍历结束
    
                    (*visit)(a.ptr->data); 
    
                    a.ptr=NULL; 
    
                } 
    
                else if(a.tag==1){ 
    
                    b=a; 
    
                    a.ptr=b.ptr->rchild; 
    
                    b.tag=0; 
    
                    Push(s,b); 
    
                } 
    
            } 
    
        }     
    
    } 
    
    }
    
    
    
    
    
    
    

    利用栈的非递归终须遍历二叉树在数据结构课本的p135上

  • 相关阅读:
    反转链表
    链表中倒数第k个结点
    调整数组顺序使奇数位于偶数前面
    词根词缀,非核心prefix/suffix/root
    核心过去式/过去完成时Past tense / past perfect
    非顺序表达
    英语连读
    图片,视频总结
    sql,explain
    @transaction注解
  • 原文地址:https://www.cnblogs.com/wangshen31/p/7998608.html
Copyright © 2020-2023  润新知