二叉树的遍历


    二叉树以lson-rson链接方式存储,以菜单方式设计并完成功能任务:建立并存储树、输出前序遍历结果、输出中序遍历结果、输出后序遍历结果、交换左右子树、统计高度,其中对于中序、后序的遍历运算要求采用非递归方式。

   建立二叉树采用先序的方法创建一个扩充二叉树。通过递归的方法,先创建一个根结点,然后再穿创建左子树,接着是创建右子树。

   前序遍历,(1)采用递归方法  先访问根结点,在遍历左子树,最后遍历右子树。(2)采用非递归的方法,用一个搜索指针,来进行搜索,首先搜索指针p指向根结点,①(a)开始访问,访问完,(b)把p的右孩子入栈,(c)p指向p的左孩子。重复上述(a)(b)(c)三个动作直到p指向空指针。②判断栈是否为空,不为空,则出栈,把这个值赋值给p,,然后重复①②直到栈空并且p指向空。

  中序遍历,(1)采用递归方法,和前序遍历相似,只不过访问根结点的顺序变了。先遍历左子树,再访问根结点,最后遍历右子树。(2)非递归的方法:这个方法也是和前序有些相似,可以参考前序的非递归来写,中序是要先遍历左子树,才访问根结点,最后遍历右子树。所以在遍历左子树的时候,先把根结点(包括子树的根结点)入栈,直到搜索指针指向空,再出栈,访问改结点,再把搜索指针指向该结点的右孩子。重复上述几个动作直到栈空并且搜索指针指向空。

  后序遍历, (2)递归方法 ,先遍历左子树,后遍历右子树,再访问根结点。 (2)非递归方法:这个和前序、中序的非递归方法还是类似的,不过要多一个标记位,来标记该结点是否能够访问。该标志位可以通过一个标志数组或者在二叉树的结构体重表示,我采用标志数组来实现。首先搜索指针p指向根结点,开始一个大循环,循环的退出条件是p指向空并且栈空,①判断p是否指向空,如果不为空,一直重复一下三个动作,将p入栈,然后标志设为0,p指向p的左孩子。标志数组的下标是和该结点在栈中的次序是相对应的。当p指向空时,此时判断栈是否为空,其结点的标识位是否为1,如果满足这两个条件,就执行以下两个动作,出栈,访问该结点。接着判断栈是否为空,如果不是,栈顶元素的标志位设为1,搜索指针指向栈顶元素的右孩子。如果为空,则跳出整个大循环(ps:如果少了这一步,就会陷入死循环,因为后序遍历,根结点最先入栈,最后被访问,如果栈空了,说明整个树已经遍历结束了,需要退出循环)

  交换左右子树,也是采用递归的方法。先将根结点的左右孩子进行交换,然后把左子树的左右孩子进行交换,最后再把右子树的左右孩子进行交换。

  统计高度,用样也是递归的方法,先求左右子树的最高值,再加上一。

源程序如下:

#include <stdio.h>
#include <stdlib.h>

struct tree
{
    int data;
    struct tree *rson;
    struct tree *lson;
};

struct stack
{
    struct tree *h[30];
    int i;
};

void menu();                          //菜单函数
struct tree* create();                //建立一个二叉树

void preorder(struct tree *T);               //先序遍历
void preorder1(struct tree *T);              //递归先序
void preorder2(struct tree *T);              //非递归先序
void inorder(struct tree *T);                //中序遍历
void inorder1(struct tree *T);              //递归中序
void inorder2(struct tree *T);              //非递归中序
void postorder(struct tree *T);               //后序遍历
void postorder1(struct tree *T);              //递归后序
void postorder2(struct tree *T);              //非递归后序
void exchange(struct tree *T);              //交换左右子树
void height(struct tree*T);                    //统计高度
int high(struct tree *T);
void quit();                             //退出函数
void push(struct stack *s,struct tree *p);  //入栈
struct tree* pop(struct stack *s);                 //出栈
struct tree* gettop(struct stack s);              //获取栈顶元素
int stackempty(struct stack s);             //栈空判断

int main()
{
    struct tree *T;
    T=NULL;
    int choice;
    menu();
    scanf("%d",&choice);
    while(choice)
    {
        switch(choice)
        {
            case 1:printf("\n请输入(0代表空结点):");T=create();break;
            case 2:if(T==NULL)
                   {
                     printf("\n二叉树为空,请先建立二叉树\n");
                     break;
                   }
                  preorder(T);break;
            case 3:if(T==NULL)
                   {
                     printf("\n二叉树为空,请先建立二叉树\n");
                     break;
                   }
                  inorder(T);break;
            case 4:if(T==NULL)
                   {
                     printf("\n二叉树为空,请先建立二叉树\n");
                     break;
                   }
                   postorder(T);break;
            case 5:if(T==NULL)
                   {
                     printf("\n二叉树为空,请先建立二叉树\n");
                     break;
                   }
                   exchange(T);break;
            case 6:if(T==NULL)
                   {
                     printf("\n二叉树为空,请先建立二叉树\n");
                     break;
                   }
                   height(T);break;
            case 7:quit();break;
            default:printf("输入无效,请重新输入:");
        }
        menu();
        scanf("%d",&choice);
    }
    return 0;
}

void menu()                          //菜单函数
{
    printf("********************************\n");
    printf("*       1.建立二叉树           *\n");
    printf("*       2.先序遍历二叉树       *\n");
    printf("*       3.中序遍历二叉树       *\n");
    printf("*       4.后序遍历二叉树       *\n");
    printf("*       5.交换二叉树左右子树   *\n");
    printf("*       6.二叉树的高度         *\n");
    printf("*       7.退出                 *\n");
    printf("********************************\n\n");
}

struct tree* create()                //建立一个二叉树
{
    struct tree *p;
    int d;
    scanf("%d",&d);
    if(d==0)
        p=NULL;
    else
    {
        p=(struct tree*)malloc(sizeof(struct tree));
        p->data=d;
        p->lson=create();
        p->rson=create();
    }
    return p;
}

void preorder(struct tree *T)               //先序遍历
{
    printf("\n递归方法的结果:\n");
    preorder1(T);
    printf("\n非递归方法的结果:\n\n");
    preorder2(T);
    printf("\n\n");

}

void preorder1(struct tree *T)              //递归先序
{
    if(T!=NULL)
    {
        printf("%d  ",T->data);
        preorder1(T->lson);
        preorder1(T->rson);
    }
}

void preorder2(struct tree *T)              //非递归先序
{
    struct stack s;
    s.i=-1;
    struct tree*p=T;
    while(p!=NULL||!stackempty(s))
    {
        while(p!=NULL)
        {
            printf("%d  ",p->data);
            push(&s,p->rson);              //右子树入栈
            p=p->lson;
        }
        if(!stackempty(s))
        {
            p=pop(&s);
        }
    }
}

void inorder(struct tree *T)                //中序遍历
{
    printf("\n递归方法的结果:\n");
    inorder1(T);
    printf("\n非递归方法的结果:\n\n");
    inorder2(T);
    printf("\n\n");
}

void inorder1(struct tree *T)              //递归中序
{
    if(T!=NULL)
    {
        inorder1(T->lson);
        printf("%d ",T->data);
        inorder1(T->rson);
    }
}


void inorder2(struct tree *T)              //非递归中序
{
     struct stack s;
    s.i=-1;
    struct tree*p=T;
    while(p!=NULL||!stackempty(s))
    {
        while(p!=NULL)
        {
            push(&s,p);
            p=p->lson;
        }
        if(!stackempty(s))
        {
            p=pop(&s);
            printf("%d ",p->data);
            p=p->rson;
        }
    }
}


void postorder(struct tree *T)              //后序遍历
{
     printf("\n递归方法的结果:\n");
    postorder1(T);
    printf("\n非递归方法的结果:\n\n");
    postorder2(T);
    printf("\n\n");
}

void postorder1(struct tree *T)              //递归后序
{

    if(T!=NULL)
    {
        postorder1(T->lson);
        postorder1(T->rson);
        printf("%d ",T->data);
    }
}

void postorder2(struct tree *T)              //非递归后序
{
     struct stack s;
    s.i=-1;
    struct tree*p=T;
    int flag[30]={0};
    while(p!=NULL||!stackempty(s))
    {
        while(p!=NULL)
        {
            push(&s,p);
            flag[s.i]=0;
            p=p->lson;
        }
        while(!stackempty(s)&&flag[s.i]==1)
        {
            p=pop(&s);
            printf("%d ",p->data);
        }
        if(!stackempty(s))
        {
            flag[s.i]=1;
            p=gettop(s);
            p=p->rson;
        }
        else
            break;
    }
}

void exchange(struct tree *T)              //交换左右子树
{
    struct tree* temp;
    if(T!=NULL)
    {
        temp=T->lson;
        T->lson=T->rson;
        T->rson=temp;
        exchange(T->lson);
        exchange(T->rson);
    }
}

void height(struct tree*T)                    //统计高度
{
    int h=0;
    h=high(T);
    printf("树的高度为:%d\n",h);

}

int high(struct tree *T)
{
    int h;
    if(T==NULL)
        h=0;
    else
    {
        h=high(T->lson)>high(T->rson)?high(T->lson):high(T->rson);
        h+=1;
    }
    return h;
}

void quit()
{
    printf("\n\n谢谢使用,再见\n\n");
    exit(0);
}

void push(struct stack *s,struct tree *p)  //入栈
{
    s->i+=1;
    s->h[s->i]=p;
}

struct tree* pop(struct stack *s)                 //出栈
{
    s->i-=1;
    return s->h[s->i+1];
}

int stackempty(struct stack s)             //栈空判断
{
    if(s.i>=0)
        return 0;
    return 1;
}

struct tree* gettop(struct stack s)       //获取栈顶函数
{
   return s.h[s.i];
}
总结:在建立二叉树是建立二叉扩充树,可以通过先序,中序,后序三种方法进行建立。前序、中序、后序的非递归方法中,由于是建立的二叉扩充树,所以每个结点都当作一个根结点来进行访问。树的定义是递归的,所以采用递归的方法对树进行运算也就比较容易了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值