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

Posted 汪神

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录一下关于二叉树的非递归遍历相关的知识,希望对你有一定的参考价值。

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

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

/**********
【题目】试利用栈及其基本操作写出二叉树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\n",treeTemp->data);
        traverseLeft(treeTemp->lchild, S, visit);//遍历左边的节点,并沿途将他们的右子树入栈,遍历后treeTemp指向最左边那个子树              
        while(!StackEmpty(S)) {
            printf("get into the stack\n"); 
            Pop(S, treeTemp);
            visit(treeTemp->data);
            printf("visit the stack of the rchild:%c\n",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\n",T->data);
        if(T->rchild && T->data!=#) {
            Push(S, T->rchild);
            if(!StackEmpty(S)) {
                printf("push %c into the stack\n",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); 

            } 

        } 

    }     

} 

}






//网上的答案:写在函数体里面就行了
/*
SElemType 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) //有两个孩子的话

        { 

            b.tag=0; 

            a.ptr=b.ptr->rchild; 

            Push(s,b); 

        } 

        else if(b.tag==0) 

        { 

            a=b; 

            while(a.tag==0&&!StackEmpty(s)) 
    
            { 
    
                (*visit)(a.ptr->data); 

                Pop(s,a); 

            } 

            if(a.tag==0&&StackEmpty(s)){ 

                (*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上

以上是关于记录一下关于二叉树的非递归遍历的主要内容,如果未能解决你的问题,请参考以下文章

《数据结构》遍历二叉树的非递归算法的疑问。

二叉树的非递归遍历

Java实现二叉树的创建递归/非递归遍历

二叉树的非递归遍历怎么写?

最简方式实现二叉树的非递归遍历

转更简单的非递归遍历二叉树的方法