二叉树遍历(递归/非递归实现)

1. tree traversal

先序preorder:节点,左孩子,右孩子

中序inorder:左孩子,节点,右孩子

后序postorder:左孩子,右孩子,节点

层序levelorder:按照节点从上到下,从左到右的顺序访问

2. 程序实现-前期

  • 二叉树定义
typedef char eletype;//二叉树结点信息类型
typedef struct BiTNode//二叉树结点类型

{
    bool flog; //为后序遍历准备,也可以不用,后面详述

    struct BiTNode *lchild,*rchild;

    eletype data;    

}BiTNode;


typedef BiTNode *elemtype;//elemtype声明为指针类型
  • 栈的相关定义
#define STACK_INIT_SIZE 100//栈初始分配的空间数

#define STACKINCREAMENT 10//栈空间不够时增加的空间数

typedef struct stack//栈的存储类型,采用动态分配

{

    elemtype *base;

    elemtype *top;

    int stacksize;

}sqstack;



sqstack *initstack()//创建栈

{

    sqstack *s;

    if (!(s = (sqstack *)malloc(sizeof(sqstack))))exit(-1);

    s->base = (elemtype *)malloc(STACK_INIT_SIZE*sizeof(elemtype));//初始化为栈分配STACK_INIT_SIZE个elemtype类型的空间

    if (!s->base)//分配空间失败

    {

        exit(-2);

        printf("栈空间分配失败!\n");

    }

    if (s->base)//分配空间成功

        printf("栈空间分配成功!\n");

    s->top = s->base;//初始化栈的头尾指针

    s->stacksize = STACK_INIT_SIZE;

    return s;

}



void push(sqstack *s,elemtype e)//压栈,e要是一个地址

{

    if (s->top-s->base>=s->stacksize)//栈满

    {

        s->base = (elemtype *)realloc(s->base,(s->stacksize+STACKINCREAMENT)*sizeof(elemtype));//栈满时增加空间

        if (!s->base)//增加分配空间失败

            exit(-2);

        s->stacksize += STACKINCREAMENT;

    }

    *(s->top) = e;

    s->top++;

}



elemtype pop1(sqstack *s)//出栈1,返回的e为栈顶元素是一个地址

{

    elemtype e;

    if (s->top == s->base)return 0;//栈空时返回

    s->top--;

    e = *(s->top);

    return e;

}



int stackempty(sqstack *s)//判断栈空,栈空返回1,否则返回0

{

    if (s->base == s->top)return 1;

    else return 0;

}
  • 先序递归法建树(即输入二叉树)
    • 方法1
BiTNode *CreateBiTree()//先序递归法建树

{

    char x;

    BiTNode *t;

    scanf("%c",&x);
    //x=getchar();
    if (x == ' ')t = NULL;

    else

    {

        if (!(t = (BiTNode *)malloc(sizeof(BiTNode))))exit(-1);

        t->data = x;//建立节点
        t->flog = false;

        t->lchild = CreateBiTree();//建左子树

        t->rchild = CreateBiTree();//建右子树

    }

    return t;

}
    • 方法2
BiTNode* BT_MakeNode(eletype target)
{
    BiTNode* pNode = (BiTNode*) malloc(sizeof(BiTNode));

    assert( NULL != pNode ); 

    pNode->data = target;
    pNode->lchild = NULL;
    pNode->rchild = NULL;
    pNode->flog =false;
    return pNode;
}


BiTNode* CreateBiTree1(eletype target, elemtype* ppTree)
{
    BiTNode* Node;

    assert( NULL != ppTree); 

    Node = *ppTree;
    if (NULL == Node)
    {
        return *ppTree = BT_MakeNode(target);
    }

    if (Node->data == target)    //不允许出现相同的元素
    {
        return NULL;
    }
    else if (Node->data > target)    //向左
    {
        return CreateBiTree1(target, &Node->lchild);
    }
    else
    {               
        return CreateBiTree1(target, &Node->rchild);
    }
}

void getNode(BiTNode* node) //对遍历出的节点的操作
{
    printf("%d ",node->data);
}
  • 对节点的操作
//void (*visit)(BiTNode*)
void getNode(BiTNode* node) //对遍历出的节点的操作
{
    printf("%d ",node->data);
}

 

3. 程序实现-核心

  • 非递归实现
PreOider
void PreOrder(BiTNode* t,void (*visit)(BiTNode*))  //前序遍历二叉树非递归算法
{
    sqstack* s;
    BiTNode* p;
    s=initstack(); //初始化栈
    p=t;
    printf("前序遍历二叉树,字符序列为:\n");
    push(s,p);
    while (!stackempty(s))
    {
        p=pop1(s);
        (*visit)(p);
        if (p->rchild!=NULL)
        {
            push(s,p->rchild);
        }
        if (p->lchild!=NULL)
        {
            push(s,p->lchild);
        }
    }
    printf("\n");

}
InOrder
void InOrder(BiTNode *t,void (*visit)(BiTNode*))//中序遍历二叉树非递归算法

{

    sqstack *s;

    BiTNode *p;

    s = initstack();//初始化栈

    p = t;

    printf("中序遍历二叉树,字符序列为:\n");

    while (p||!stackempty(s))

    {

        while (p)//找最左结点

        {

            push(s,p);

            p = p->lchild;//p指针顺lchild而下

        }

        p = pop1(s);//栈顶元素出栈以访问最左结点

        (*visit)(p);//访问最左结点

        p = p->rchild;

    }

    printf("\n");

}
PostOrder_1(需要标志位)
//需要标志位flog
void PostOrder_1(BiTNode* t,void (*visit)(BiTNode*))
{

    sqstack *s;

    BiTNode* p;
   
    s = initstack();//初始化栈

     p=t;

    printf("后序遍历二叉树,字符序列为:\n");

    while (p||!stackempty(s))

    {

        while (p)//找最左结点

        {

            push(s,p);

            p = p->lchild;//p指针顺lchild而下

        }

        s->top--;
        p=*(s->top);
        s->top++;
        //p=pop1(s);
        //push(s,p);
        if (!p->rchild||p->flog)
        {
            p=pop1(s);
            (*visit)(p);
            p=NULL; //指向空,防止下次循环中while(p)的循环出错
        }
        else
        {
            p->flog=true;
            p=p->rchild;
            
        }
    }

    printf("\n");
}
PostOrder_2
//记住一点:你输出的节点同时也是上一级(如果存在的话)的右孩子。
void PostOrder_2(BiTNode* root,void (*visit)(BiTNode*))
{
    sqstack* s;
    BiTNode* p;
    s=initstack();
    p=NULL;
    while (root||!stackempty(s))
    {
        if (root) //寻找右节点
        { 
            push(s,root); 
            root = root->lchild; 
        } 
        else 
        { 
            s->top--;
            root=*(s->top);
            s->top++;
            if (root->rchild!=NULL && p!=root->rchild) 
            { //如果这个节点标记过,就证明root节点的右孩子已经遍历过了,不要重复
                root=root->rchild; 
            } 
            else
            { 
                s->top--;
                p=root=*(s->top); //标记这个节点
                s->top++; 
                (*visit)(p);
                pop1(s);
                root=NULL; 
            } 
        } 

    }
    printf("\n");
}
  • 层序遍历LevelOrder

我们如果仔细揣摩,把preorder中的栈换成队列就得到了层序遍历了(LIFO-->FIFO)。

LevelOrder
void LevelOrder(BiTNode* t,void (*visit)(BiTNode*))  
{
    sqQUEUE* q;
    BiTNode* p;
    q=initQUEUE(); //初始化队列
    p=t;
    printf("层序遍历二叉树,字符序列为:\n");
    QUEUEput(s,p);
    while (!QUEUEempty(s))
    {
        p=QUEUEget(s);
        (*visit)(p);
        if (p->lchild!=NULL)
        {
            QUEUEput(s,p->lchild);
        }
        if (p->rchild!=NULL)
        {
            QUEUEput(s,p->rchild);
        }
    }
    printf("\n");

}
  • 递归实现

以前序遍历为例,递归很简单。若果我们把(*visit)函数的调用移到递归调用中间,就是中序遍历;移到递归调用之后,就成了后序遍历。

traverse
void traverse(BiTNode *t,void (*visit)(BiTNode*))
{
    if (t==NULL)
    {
        return;
    }
    (*visit)(t);
    traverse(t->lchild,getNode);
    traverse(t->rchild,getNode);
}

4. 程序测试

int main()
{
    int i;
    BiTNode *t=NULL;

    printf("请输入建树字符序列,以1表示NULL:\n");
    t = CreateBiTree();    //注意前序递归法建树的方法

    //srand( (unsigned)time( NULL ) ); 

    //for (i=0; i<10; i++)
    //{
    //    CreateBiTree1(rand()/100, &t);
    //}

    traverse(t,getNode); //递归实现遍历
    printf("\n");
    PreOrder(t,getNode);
    InOrder(t,getNode);
    PostOrder_1(t,getNode);
    PostOrder_2(t,getNode);
    return 0;
}

 

本文参考:

http://blog.csdn.net/rainer7/article/details/70671

http://www.cppblog.com/ngaut/archive/2011/11/27/2351.html

posted @ 2012-08-02 00:15  csqlwy  阅读(2217)  评论(1编辑  收藏  举报