数据结构实验 实验3 二叉树的遍历

一、【实验目的】

  1. 了解二叉树的前序、中序、后序和层次序列排列;
  2. 将C语言同二叉树的数据结构联系起来;
  3. 掌握生成的二叉树的链表结构;
  4. 掌握如何按层次输出二叉树的所有结点;
  5. 掌握如何将动态二叉树转换为静态二叉链表。

 

二、【实验内容】

创建一个二叉树,对这棵动态二叉树进行分析,将其用静态二叉链表表示。二叉树的动态二叉链表结构中的每个结点有三个字段:data,lchild,rchild。静态二叉链表是用数组作为存储空间,每个数组元素存储二叉树的一个结点,也有三个字段:data,lchild,rchild。lchild和rdhild分别用于存储左右孩子的下标。

 

三、【实验步骤与要求】

1、实验前的准备

(1)了解二叉树的基本概念;

(2)了解二叉树的基本结构。

2、上机操作

(3)了解二叉树的前序和中序序列排列;

    1. 将C语言同二叉树的数据结构联系起来;
    2. 掌握生成的二叉树的链表结构;
    3. 掌握如何按层次输出二叉树的所有结点;
    4. 掌握如何将动态二叉树转换为静态二叉链表。

 

#include<stdio.h>
#include<stdlib.h>
//函数结果状态代码
#define TRUE            1
#define FALSE           0
#define OK              1
#define ERROR           0
#define INFEASIBLE      -1
#define OVERFLOW        -2

#define MAX_StaticTree  100
typedef int Status;         //Status是函数的类型,其值是函数结果代码
typedef char TElemType;     //树结点数据类型定义为char型

//------二叉树的二叉链表存储表示-------
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild,*rchild; //左右孩子指针,指向孩子结点
    int index;                      //先序创建时的标号
}BiTNode,*BiTree;                   //结构体变量,原型和指针型

//------用数组存储的静态树存储表示-----
typedef struct static_BiTNode
{
    TElemType data;
    int lchild,rchild;   //lchild和rdhild分别用于存储左右孩子的下标。
}static_BiTNode;


//------基本操作的函数原型说明------
static int counts=0;     //用于给结点标号
Status CreateBiTree(BiTree *T);
    //按先序次序输入二叉树中结点的值(一个字符),#字符表示空树,
    //构造二叉链表表示的二叉树T。
Status PrintElement(TElemType e);
    //最简单的Visit函数
    //输出元素e的值
Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e));
    //采用二叉链表存储方式,Visit是对结点操作的应用函数。
    //先序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
    //一旦Visit()失败,则操作失败
Status InOrderTraverse(BiTree T,Status (*Visit)(TElemType e));
    //采用二叉链表存储方式,Visit是对结点操作的应用函数。
    //中序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
    //一旦Visit()失败,则操作失败
Status PostOrderTraverse(BiTree T,Status (*Visit)(TElemType e));
    //采用二叉链表存储方式,Visit是对结点操作的应用函数。
    //后序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
    //一旦Visit()失败,则操作失败
Status LevelOrderTraverse(BiTree T,Status (*Visit)(TElemType e));
    //采用二叉链表存储方式,Visit是对结点操作的应用函数。
    //层序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
    //一旦Visit()失败,则操作失败
int LevelSub(BiTree T, int level,Status (*Visit)(TElemType e));
    //层序辅助递归函数
Status TreeToArray(BiTree T,static_BiTNode t[]);
    //将动态二叉树转换为静态二叉链表
    //按先序次序给结点编号,lchild和rdhild分别用于存储左右孩子的下标

int main()
{
    BiTree T;
    static_BiTNode  a[MAX_StaticTree];//静态二叉链表是用数组作为存储空间
    CreateBiTree(&T);           //创建二叉树

    printf("先序:");
    PreOrderTraverse (T,PrintElement);printf("\n");
    printf("中序:");
    InOrderTraverse(T,PrintElement);printf("\n");
    printf("后序:");
    PostOrderTraverse(T,PrintElement);printf("\n");
    printf("层序:");
    LevelOrderTraverse(T,PrintElement);printf("\n");

    TreeToArray(T,a);       //动态转静态
    printf("静态二叉链表为:\n");   //输出及格式
    printf("counts\tdata\tlchild\trchild\t\n");
    int m;
    for(m=0;m<counts;m++)       //counts用于给结点标号
        printf("%d\t%c\t%d\t%d\n",m,a[m].data,a[m].lchild,a[m].rchild);
return 0;
}

//------基本操作的函数实现------
Status CreateBiTree(BiTree *T){
    //按先序次序输入二叉树中的结点的值(一个字符),#字符表示空树,
    //构造二叉链表表示的二叉树T。
    //注意:叶子结点后要输入两个#来表示左右子树都为空
    char ch;scanf("%c",&ch);
    if(ch == '#')   *T = NULL;
    else{
        if (!(*T = (BiTNode *)malloc(sizeof(BiTNode))))  exit(OVERFLOW);
        (*T)->data = ch;            //生成根结点
        (*T)->index= counts++;      //给结点标号
        CreateBiTree(&(*T)->lchild);//构造左子树
        CreateBiTree(&(*T)->rchild);//构造右子树
    }
    return OK;
}

Status PrintElement(TElemType e){//输出元素e的值
    printf("%c",e);
    return OK;
}

Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
    //采用二叉链表存储方式,Visit是对结点操作的应用函数,
    //先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
    if (T){//DLR
        if (Visit(T->data))
            if (PreOrderTraverse(T->lchild,Visit))
                if (PreOrderTraverse(T->rchild,Visit))  return OK;
        return ERROR;
    }else return OK;
}

Status InOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
    //采用二叉链表存储方式,Visit是对结点操作的应用函数,
    //中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
    if (T){//LDR
        if (InOrderTraverse(T->lchild,Visit))
            if (Visit(T->data))
                if (InOrderTraverse(T->rchild,Visit))  return OK;
        return ERROR;
    }else return OK;
}

Status PostOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
    //采用二叉链表存储方式,Visit是对结点操作的应用函数,
    //后序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
    if (T){//LRD
        if (PostOrderTraverse(T->lchild,Visit))
            if (PostOrderTraverse(T->rchild,Visit))
                if (Visit(T->data)) return OK;
        return ERROR;
    }else return OK;
}

Status LevelOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
    //采用二叉链表存储方式,Visit是对结点操作的应用函数,
    //层序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
    int i = 0;
    for (i=1; ;i++) {//从第1层开始遍历
        if (!LevelSub(T, i,Visit))//遍历失败就跳出循环
            break;
    }
    return OK;
}

int LevelSub(BiTree T, int level,Status (*Visit)(TElemType e)){
	if (!T || level<1)  //如果树为空或者层次小于1就遍历失败
		return 0;       //遍历失败返回0
	if (level==1) {     //层次等于1就访问树根结点
		Visit(T->data); //遍历根结点
		return 1;
	}//左右子树递归
	return LevelSub(T->lchild,level-1,Visit) + LevelSub(T->rchild,level-1,Visit);
}

static int num=0;//用于转换为静态函数
Status TreeToArray(BiTree T,static_BiTNode t[]){
    t[num].data=T->data;                //数据赋值
    if (T->lchild==NULL)    //左孩子为空则置-1
        t[num].lchild=-1;
    else
        t[num].lchild=T->lchild->index;

    if (T->rchild==NULL)    //右孩子为空则置-1
        t[num].rchild=-1;
    else
        t[num].rchild=T->rchild->index;

    num++;

    if (T->lchild!=NULL)    //左孩子不空左递归
        TreeToArray(T->lchild,&t[0]);
    if (T->rchild!=NULL)    //右孩子不空左递归
        TreeToArray(T->rchild,&t[0]);
return OK;
}

/*
测试数据(P129图6.9)
-+a##*b##-c##d##/e##f##
*/


 

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值