二叉树的几种遍历方式

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <malloc.h>

#define TRUE  1
#define FALSE 0
#define OK    1
#define ERROR 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10


typedef int ElementType;	// 定义元素的类型
typedef int Status;	    // 定义函数返回值状态

// 二叉树定义
typedef struct BNode
{
    ElementType data;
    struct BNode *lchild;
    struct BNode *rchild;
} BNode;

// 定义栈的结构
typedef BNode * SElemType;
typedef struct
{
    SElemType *base;
    SElemType * top;
    int stacksize;
} SqStack;


typedef BNode * QElemType;

typedef struct QNode
{
    QElemType  data;
    struct QNode *next;
} QNode;

typedef struct
{
    QNode * front;
    QNode * rear;
} LinkQueue;

Status InitStack (SqStack &S);         // 初始化栈
Status GetTop(SqStack S, SElemType &e); //
Status Push(SqStack &S, SElemType e);
Status Pop(SqStack &S, SElemType &e);
Status StackEmpty(SqStack S);

Status InitQueue(LinkQueue &Q);  /*初始化队列*/
Status QueueEmpty(LinkQueue Q);  /*判断队列是否为空*/
Status DestroyQueue(LinkQueue &Q); /*销毁队列*/
Status EnQueue(LinkQueue &Q, QElemType e); /*入队列*/
Status DeQueue(LinkQueue &Q, QElemType &e); /*出队列*/

Status CreateBiTree(BNode * &T );  /*生成二叉链表*/
void PreOrderTraverse(BNode *T);  /*先序遍历二叉树*/
void InOrderTraverse(BNode *T);  /*中序遍历二叉树*/
void PostOrderTraverse(BNode *T); /*后序遍历二叉树*/
void LevelOrderTraversal(BNode *T); /*按层次遍历二叉树*/
void InTraverse(BNode *T);  /*中序非递归遍历二叉树*/
void PreTraverse(BNode *T);  /*先序非递归遍历二叉树*/
void PostTraverse(BNode *T); /*后序非递归遍历二叉树*/

int main()
{
    BNode * bt;
    printf("生成二叉树\n");
    CreateBiTree(bt);

    printf("\n先序递归遍历二叉树\n");
    PreOrderTraverse(bt);

    printf("\n进行先序非递归遍历\n");
    PreTraverse(bt);

    printf("\n中序递归遍历二叉树\n");
    InOrderTraverse(bt);

    printf("\n进行中序非递归遍历\n");
    InTraverse(bt);

    printf("\n后序递归遍历二叉树\n");
    PostOrderTraverse(bt);

    printf("\n进行后序非递归遍历\n");
    PostTraverse(bt);

    printf("\n层序遍历二叉树\n");
    LevelOrderTraversal(bt);

    return 0;
}

// 创建二叉树
CreateBiTree(BNode * &T)
{
    int data;
    scanf("%d", &data);

    if(!data)
        T = NULL;
    else
    {
        if(!(T = (BNode * ) malloc(sizeof(BNode))))
            exit(OVERFLOW);
        T->data = data;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
    return OK;
}


/*先序遍历二叉树*/
void PreOrderTraverse(BNode *T)
{
    if (T)
    {
        printf("%d ", T->data);
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

/*中序遍历二叉树*/
void InOrderTraverse(BNode *T)
{
    if(T)
    {
        InOrderTraverse(T->lchild);
        printf("%d ", T->data);
        InOrderTraverse(T->rchild);
    }
}

/*后序遍历二叉树*/
void PostOrderTraverse(BNode *T)
{
    if(T)
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        printf("%d ", T->data);
    }
}


/*按层次遍历二叉树*/
void LevelOrderTraversal(BNode * T)
{

    LinkQueue Q;
    BNode * p;

    if(!T)
        return ;

    InitQueue(Q);	// 创建并初始化
    EnQueue(Q, T);

    if(!Q.front)
        printf("EnQueue\n");
    while(!(QueueEmpty(Q)))
    {
        DeQueue(Q, p);
        printf("%d ", p->data); // 获取访问出队列的节点
        if(p->lchild)
            EnQueue(Q, p->lchild);
        if(p->rchild)
            EnQueue(Q, p->rchild);
    }
    printf("\n");
}

/*先序非递归遍历二叉树*/
void PreTraverse(BNode *T)
{
    SqStack S;
    BNode * p;
    InitStack(S);

    p = T;
    while(p || !StackEmpty(S))
    {
        if(p)
        {
            printf("%d ", p->data);
            Push(S, p);
            p = p->lchild;
        }
        else
        {
            Pop(S, p);
            p = p->rchild;
        }
    }// endwhile

    printf("\n");
}

/*中序非递归遍历二叉树*/
void InTraverse(BNode *T)
{

    SqStack S;
    BNode *p ;
    InitStack(S);	// 初始化栈操作

    p = T;

    // P 不为空或者栈不为空的时候进行遍历
    while(p || !StackEmpty(S))
    {
        if ( p )
        {
            Push(S, p);
            p = p->lchild; // 进行遍历左子树
        }
        else
        {
            Pop(S, p);
            printf("%d ", p->data);

            p = p->rchild ; // 进行遍历右子树
        }
    }
    printf("\n");
}


/*后序非递归遍历二叉树*/
/*
后续非递归遍历二叉树,需要注意的是退栈的如果是左孩子,接下来需要把栈顶元素(双亲)的右孩子入栈;
如果栈顶元素没有右孩子,则访问栈顶元素。
或者栈顶元素的右孩子已经被访问过了,则访问栈顶元素。
那么如何知道当前应该访问栈顶元素,还是应该把栈顶元素的右孩子入栈呢?
解决这个问题常用的方法有两类,一类是设置标志数组,标记该结点的右孩子是否被访问过。
还有一类是设一个辅助指针,存放后序遍历时的前驱结点地址。如果后序遍历时的前驱结点是栈顶的右孩子,则栈顶元素出栈并访问。
*/
void PostTraverse(BNode *T)
{
    SqStack s;
    BNode * p, *pre;
    InitStack(s);

    p = T;
    pre = NULL; // pre 表示后续遍历时的前驱

    while( p || !StackEmpty(s))
    {
        // 左孩子入栈,一直到二叉树的左下结点
        if(p)
        {
            Push(s, p);
            p = p->lchild;
        }
        else
        {
            GetTop(s, p);// 取栈顶元素
            // 如果栈顶元素没有右孩子或者右孩子是遍历的前驱,则访问该结点
            if(p->rchild == NULL || p->rchild == pre)
            {
                printf("%d ", p->data);
                Pop(s, p);
                pre = p;
                p = NULL;
            }
            else
            {
                // 否则,说明栈顶元素的右子树还没有被访问,则右子树准备入栈
                p = p->rchild;
            }
        }
    }

    printf("\n");
}




/*初始化队列*/
Status InitQueue(LinkQueue &Q)
{
    Q.front = Q.rear = (QNode * )malloc(sizeof(QNode));
    if(!Q.front)
        exit(OVERFLOW);
    Q.front->next = NULL;
    return OK;
}

/*判断队列是否为空*/
Status QueueEmpty(LinkQueue Q)
{
    return (Q.front == Q.rear) ? OK : ERROR;
}

/*销毁队列*/
Status DestroyQueue(LinkQueue &Q)
{
    while(Q.front)
    {
        Q.rear = Q.front->next;
        free(Q.front);
        Q.front = Q.rear;
    }

    return OK;
}

/*入队列*/
Status EnQueue(LinkQueue &Q, QElemType e)
{
    QNode * p;
    if(!(p = (QNode *) malloc(sizeof(QNode))))
        exit(OVERFLOW);

    p->data = e;
    p->next = NULL;

    Q.rear -> next = p;
    Q.rear = p;

    return OK;
}

/*出队列*/
Status DeQueue(LinkQueue &Q, QElemType &e)
{
    QNode *p;
    if(Q.front == Q.rear)
        return ERROR;

    p = Q.front->next;
    e = p->data;

    Q.front->next = p->next;
    if(Q.rear == p)
        Q.rear = Q.front;
    return OK;
}

Status InitStack (SqStack  &S)
{
    S.base = (SElemType *) malloc (STACK_INIT_SIZE * sizeof(SElemType));
    if(!S.base)
        exit(OVERFLOW);
    S.top = S.base;
    S.stacksize = STACK_INIT_SIZE;
    return OK;
}

Status GetTop(SqStack S, SElemType &e)
{
    if(S.base == S.top)
        return ERROR;
    e = *(S.top - 1);
    return ERROR;
}

// 进行入栈操作
Status Push(SqStack &S, SElemType e)
{
    if(S.top - S.base >= STACK_INIT_SIZE)
    {
        S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
        if(!S.base)
            exit(OVERFLOW);

        S.top = S.base + S.stacksize;
        S.stacksize += STACK_INIT_SIZE;
    }

    * S.top++ = e;
    return OK;
}

// 进行出栈操作
Status Pop(SqStack &S, SElemType &e)
{
    if(S.top == S.base)
        return ERROR;

    e = * --S.top;
    return OK;
}

// 判断栈是否为空
Status StackEmpty(SqStack S)
{
    return (S.base == S.top) ? 1 : 0 ;
}

构造的二叉树

 

测试数据:1 2 4 8 0 0 9 10 0 0 11 0 0 5 0 0 3 6 0 0 7 0 0

测试结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值