数据结构 树笔记-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");

 

}

猜你喜欢

转载自blog.csdn.net/linking_lin/article/details/80356571