二叉樹層次遍歷及三種遍歷的非遞歸寫法

層次遍歷利用隊列,很容易實現,先根節點入隊,出隊,每次出隊檢查左右子節點是否爲空,非空則入隊,如此往復直至隊空,代碼如下

 

//層次遍歷輸出二叉樹

void levelOrder(BiTree biT){

    printf("層次遍歷結果:\n");

    initQueue(&sqQueue);

    BiTree p;

    enQueue(&sqQueue,biT);

    while(!isEmpty(sqQueue)){

        deQueue(&sqQueue,&p);

        printf("%d ",p->data);

        if(p->lchild!=NULL)

            enQueue(&sqQueue,p->lchild);

        if(p->rchild!=NULL)

            enQueue(&sqQueue,p->rchild);

    }

}

 

 

前序遍歷非遞歸依靠棧實現,相對來說比較簡單,先來用手寫模擬一下基本就能知道怎麼寫了

https://img2018.cnblogs.com/blog/1104670/201810/1104670-20181011115909648-414299834.png

 

據此可得如下代碼

void preOrder_stack(BiTree T){

    printf("\n非遞歸先序遍歷結果:\n");

    initStack(&sqStack);

    BiTree p=T;

    push(&sqStack,p);

    while(!stackEmpty(sqStack)){

        pop(&sqStack,&p);

        printf("%d ",p->data);

        if(p->rchild){

            push(&sqStack,p->rchild);

        }

        if(p->lchild){

            push(&sqStack,p->lchild);

        }

    }

}

 

 

 

中序遍歷比前序要稍微複雜些,我也先用手寫理出思路

https://img2018.cnblogs.com/blog/1104670/201810/1104670-20181011194958895-1466641197.png

代碼寫的和書上的一比。。。感覺麻煩了好多,但畢竟是自己理的思路不容易忘,所以還是貼自己的

void inOrder_stack(BiTree T){

    printf("\n非遞歸中序遍歷結果:\n");

    initStack(&sqStack);

    BiTree p=T,l;//l用於保存上次的輸出

    push(&sqStack,p);

    while(!stackEmpty(sqStack)){

        getTop(&sqStack,&p);

        if(p->lchild!=NULL&&p->lchild!=l){

            push(&sqStack,p->lchild);

        }

        else {

            pop(&sqStack,&l);

            printf("%d ",l->data);

            if(l->rchild!=NULL){

                push(&sqStack,l->rchild);

            }

            else if(l->rchild==NULL){

                if(!stackEmpty(sqStack)){

                    pop(&sqStack,&l);

                    printf("%d ",l->data);

 

                    if(l->rchild!=NULL){

                        push(&sqStack,l->rchild);

                    }

                }

            }

        }

    }

}

 

 

 

後序應該是三種裏面最複雜的一個了,如下

https://img2018.cnblogs.com/blog/1104670/201810/1104670-20181011201547706-2033860924.png

代碼如下

void postOrder_stack(BiTree T){

    printf("\n非遞歸後序遍歷結果:\n");

    initStack(&sqStack);

    BiTree p=T,l;//l用於保存最近一次pop出的節點

    push(&sqStack,p);

    while(!stackEmpty(sqStack)){

        getTop(&sqStack,&p);

        if(p->lchild!=NULL){

            if(l!=p->lchild&&l!=p->rchild){//若左右子節點均未被訪問過,推入左子節點

                push(&sqStack,p->lchild);

            }

            else if(l==p->lchild){//左子節點訪問過,若右子節點非空,則壓入右子節點,否則,輸出

                if(p->rchild!=NULL)

                    push(&sqStack,p->rchild);

                else if(p->rchild==NULL){

                    pop(&sqStack,&l);

                    printf("%d ",l->data);

                }

            }

            else if(l==p->rchild){//右子節點訪問過,則左右子節點均訪問完,彈出當前節點

                pop(&sqStack,&l);

                printf("%d ",l->data);

            }

        }

        else if(p->lchild==NULL){

            if(p->rchild==NULL){//左右子節點爲空,則直接彈出,彈出節點保存在l中

                pop(&sqStack,&l);

                printf("%d ",l->data);

            }

            else if(p->rchild!=NULL){

                    if(l==p->rchild){//右子節點訪問過,則左右子節點均訪問完,彈出當前節點

                    pop(&sqStack,&l);

                    printf("%d ",l->data);

                }else if(l!=p->rchild){

                    push(&sqStack,p->rchild);

                }

            }

        }

    }

}

 

由第一張圖可以看出,每次輸出時,棧頂自上而下保存的是該節點到根節點的路徑,這是個很有用的特性,所以後序遍歷雖然複雜些但也得掌握。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章