1. 程式人生 > >資料結構 樹筆記-6 二叉樹的非遞迴先序遍歷

資料結構 樹筆記-6 二叉樹的非遞迴先序遍歷

如下這棵二叉樹的先序遍歷結果為:ABDEFPC

針對於上面的這棵二叉樹,結合程式碼,講述遍歷過程

#include <stdio.h>

#include <malloc.h>

 

//#define ElemType char

typedef char ElemType;

 

typedef struct BiTNode{

    ElemType data;

    struct BiTNode *lchild, *rchild;

}BiTNode, *BiTree;

 

#define MAX 10000

typedef struct{

    BiTree data[MAX];

    int top;

}SeqStack;

 

對上圖的二叉樹,按照程式碼的思路說明如何用非遞迴的方式遍歷一棵二叉樹:

 

void pre_order_nonrecursive(BiTree T)

{

    SeqStack s;

    s.top = -1;

 

    BiTree tmp = T;

 

    while(tmp){// while1開始

        while(tmp){// while2 開始

            printf("%c",tmp->data);

 

            if(tmp->rchild){

                if(s.top == MAX-1){

                    exit(0);

                }else{

                    s.data[++s.top] = tmp->rchild;

                }              

            }

            tmp = tmp->lchild;

        }// while2結束

 

        if(s.top != -1){

            tmp = s.data[s.top--];

        }

    }// while1結束     printf("\n");

}

 

tmp結點的來源:

如果tmp的左孩子不為空,就把這個左孩子更新給tmp;

否則,

如果棧不為空,就把棧頂元素彈出並更新給tmp;

如果棧為空,說明這棵二叉樹遍歷完畢

T = A

tmp = T =A

列印A

A的右孩子存在為結點C,不為空

s.stop = -1<10000,此時棧為空,棧不滿

C(的地址)入棧,同時棧頂指標stop1變為0

 

tmp=A的左孩子=B

列印B

B的右孩子存在為結點P,不為空

s.stop = 0<10000,此時棧不滿

P(的地址)入棧同時棧頂指標stop1變為1

 

tmp=B的左孩子=D

列印D

D的右孩子存在為結點E,不為空

s.stop = 1<10000,此時棧不滿

E(的地址)入棧同時棧頂指標stop1變為2

 

tmp=D的左孩子=

s.stop = 2>-1,此時棧不空

從棧中彈出棧頂元素Etmp

同時棧頂指標stop1變為1

 

tmp=E

列印E

E沒有右孩子,不進行入棧操作

 

tmp=E的左孩子=F

列印F

F沒有右孩子,不進行入棧操作

 

tmp=F的左孩子=

s.stop = 1>-1,此時棧不空

從棧中彈出棧頂元素Ptmp

同時棧頂指標stop1變為0

 

tmp=P

列印P

P沒有右孩子,不進行入棧操作

 

tmp=P的左孩子=

s.stop = 0>-1,此時棧不空

從棧中彈出棧頂元素Ctmp

同時棧頂指標stop1變為-1

 

tmp=C

列印C

C沒有右孩子,不進行入棧操作

 

tmp=C的左孩子=

s.stop = -1,棧空,不能進行彈棧操作

 

Tmp=

 

先序遍歷結束:

列印結果為ABDEFPC


程式碼:
#include <stdio.h>
#include <malloc.h>

//#define ElemType char
typedef char ElemType;

typedef struct BiTNode{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

#define MAX 10000
typedef struct{
    BiTree data[MAX];
    int top;
}SeqStack;
void pre_order_nonrecursive(BiTree T)
{
    SeqStack s;
    s.top = -1;

    BiTree tmp = T;

    while(tmp){
        while(tmp){
            printf("%c",tmp->data);

            if(tmp->rchild){
                if(s.top == MAX-1){
                    exit(0);
                }else{
                    s.data[++s.top] = tmp->rchild;
                }
            }
            tmp = tmp->lchild;
        }

        if(s.top != -1){
            tmp = s.data[s.top--];
        }
    }
    printf("\n");
}

對上述程式碼 的 實現過程進行概述

二叉樹的非遞迴先序遍歷

#define MAX 10000

巨集定義是簡單的符號代換,這裡MAX符號的含義是棧中最多存放10000個結點的地址

typedef struct{

自定義一個結構體型別用於 棧操作

    BiTree data[MAX];

定義一個數組型別的變數,用於儲存棧中的元素

作為先序遍歷,棧中存放的都是樹中某個結點的右孩子

    int top;

定義棧的棧頂指標top,它始終指向棧頂元素

}SeqStack;

 

void pre_order_nonrecursive(BiTree T)

引數T:即將被遍歷的樹的 樹根地址

{

 

    SeqStack s;

宣告棧

    s.top = -1;

初始化棧的棧頂指標為-1,因為陣列的第一個元素的下標是0,而此時作為棧的這個數組裡面沒有存放資料

 

 

    BiTree tmp = T;

宣告一個結點指標型別的變數tmp用於遍歷樹,並初始化為樹根地址

 

 

    while(tmp){

外層while迴圈:

tmp結點一開始是根結點,

之後就是每一個左枝的最後一個右孩子,

也是從棧中彈出的棧頂元素

        while(tmp){

內層while迴圈:遍歷窮盡結點tmp的左枝

            printf("%c",tmp->data);

先序遍歷:根左右,所以拿到一個不為空的結點的時候,應首先列印這個結點的資料

 

 

            if(tmp->rchild){

如果當前這個結點有右孩子

                if(s.top == MAX-1){

並且 如果棧滿

                    exit(0);

棧的容量不足以支援後序的先序遍歷操作,立即退出程式,不繼續再做任何操作

                }else{

並且 如果棧不滿

                    s.data[++s.top] = tmp->rchild;

把當前結點的右孩子的地址存到棧中,因為它以及它的子樹還沒有被遍歷;同時作為資料進棧的配套棧操作,把棧指標加一

                }

 

            }

 

            tmp = tmp->lchild;

為了遍歷窮盡結點tmp的左枝,把tmp更新為當前結點的左孩子地址

        }

 

 

 

        if(s.top != -1){

此時tmp結點的左枝遍歷窮盡,

如果棧不為空,需要彈出棧頂元素,並把tmp更新為這個元素,

這個棧頂元素是左枝上的最後一個有右孩子的結點的右孩子

            tmp = s.data[s.top--];

 

        }

 

    }     printf("\n");

 

}