数据结构--创建并输出二叉树的c语言实现(超详细注释/实验报告)

数据结构–创建并输出二叉树的c语言实现(超详细注释/实验报告)

知识小回顾

之前我们都是学习的线性结构,这次我们就开始学习非线性结构——树。线性结构中结点间具有唯一前驱、唯一后继关系,而非线性结构中结点的前驱、后继的关系并不具有唯一性。在树结构中,节点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。直观地看,树结构是具有分支关系的结构(其分叉、分层的特征类似于自然界中的树)。树结构应用非常广泛,特别是在大量数据处理(如在文件系统、编译系统、目录组织等)方面显得更加突出。

实验题目

创建并输出二叉树

实验目的

  1. 熟悉二叉树的结点的结构
  2. 采用链式存储表示
  3. 以广义表形式输入二叉树
  4. 使用栈保存尔察使书的根结点
  5. 输出方式采用凹入表示法
    在这里插入图片描述

实验要求

  1. 采用链式存储表示
  2. 以广义表形式输入二叉树
  3. 使用栈保存尔察使书的根结点
  4. 输出方式采用凹入表示法

实验内容和实验步骤

1.需求分析

用户输入二叉树的广义表形式,程序输出二叉树

2. 概要设计

设计创建和输出二叉树的函数,然后再主函数中调用这两个函数来实现操作。

3. 详细设计

导入一些库,并定义结点的最大个数以及树中数据的类型。
  • 定义二叉树的链式存储结构,有三个域:数据域,左孩子域,右孩子域
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 255
//定义二叉树的链式存储结构,有三个域:数据域,左孩子域,右孩子域
typedef struct BiNode
{
    char data;
    struct BiNode *lc;
    struct BiNode *rc;
}BiTree;
以广义表的形式创建二叉树
  • 算法比较复杂,我画了个流程图,跟着这个图可以比较清晰地理解算法。
  • 由于是链式存储,最后只用返回一个根节点bt就行了,其他结点直接顺藤摸瓜即可。
//以广义表的形式创建二叉树
BiTree *CreatBiTreepre(char *str)
{
    BiTree *bt,*stack[MAXSIZE],*p=NULL;
    int top=-1,k,j=0;
    char ch;
    bt=NULL;
    ch=str[j];
    while(ch!='\0')
    {
        switch(ch)
        {
        case '(':
            {
                top++;
                stack[top]=p;
                k=1;
                break;
            }
        case ')':
            {
                top--;
                break;
            }
        case ',':
            {
                k=2;
                break;
            }
        default:
            {
                p=(BiTree *)malloc(sizeof(BiTree));
                p->data=ch;
                p->lc=p->rc=NULL;
                if(bt==NULL)
                {
                    bt=p;
                }
                else
                {
                    switch(k)
                    {
                    case 1:
                        {
                            stack[top]->lc=p;
                            break;
                        }
                    case 2:
                        {
                            stack[top]->rc=p;
                            break;
                        }
                    }
                }
            }
        }
        j++;
        ch=str[j];
    }
    return bt;//链式存储只用知道一个,后面顺藤摸瓜就都知道了
}

在这里插入图片描述
在这里插入图片描述

采用凹入法输出二叉树
  • 算法同样比较复杂,也是跟着流程图来~
//采用凹入法输出二叉树
void OutBiTree(BiTree *bt)
{
    BiTree *stack[MAXSIZE],*p;
    int feature[MAXSIZE][2],top,n,i,width=4;
    char type;
    if(bt!=NULL)
    {
        top=1;
        stack[top]=bt;
        feature[top][0]=width;
        feature[top][1]=2;
        while(top>0)
        {
            p=stack[top];
            n=feature[top][0];
            switch(feature[top][1])
            {
            case 0:
                {
                    type='l';
                    break;
                }
            case 1:
                {
                    type='R';
                    break;
                }
            case 2:
                {
                    type='G';
                    break;
                }
            }
            for(i=1;i<=n;i++)
                printf(" ");
            printf("%c(%c)\n",p->data,type);
            top--;
            if(p->lc!=NULL)
            {
                top++;
                stack[top]=p->lc;
                feature[top][0]=n+width;
                feature[top][1]=0;
            }
            if(p->rc!=NULL)
            {
                top++;
                stack[top]=p->rc;
                feature[top][0]=n+width;
                feature[top][1]=1;
            }

        }
    }
}

在这里插入图片描述

树状打印二叉树
  • 二叉树的横向显示是竖向显示逆时针旋转90°。
void PrintTree(BiTree *bt,int nLayer)
{
    if(bt==NULL)
        return ;
    PrintTree(bt->rc,nLayer+1);
    for(int i=0;i<nLayer;i++)
        printf("  ");
    printf("%c\n",bt->data);
    PrintTree(bt->lc,nLayer+1);
}

主函数部分,把程序功能打印出来,并对用户做一个引导。
在这里插入图片描述

int main()//(A(B(D,),C(,E)))   (A(B(D,E),C(F,G)))  ((((A),B)),(((),D),(E,F)))这个不是树
{
    BiTree *bt;
    char *gyb,str[MAXSIZE];
    int j=1;
    printf("-----------------------------------------------------");
    printf("\n            程序功能");
    printf("\n 1.将按照输入的二叉广义表表示字符串 ");
    printf("\n · 生成对应的二叉树链式结构。");
    printf("\n 2.输出二叉树的凹入法表示形式。");
    printf("\n · G--根 L--左孩子 R--右孩子");
    printf("\n 3.树状打印二叉树");
    printf("\n · 逆时针旋转90度显示二叉树");
    printf("\n * 输入示例:(A(B(D,),C(,E)))或(A(B(D,E),C(F,G)))");
    printf("\n-----------------------------------------------------\n");
    printf("请输入二叉树的广义表形式:\n");
    gyb=str;
    scanf("%s",str);
    bt =CreatBiTreepre(gyb);
    printf("二叉树建立成功!\n");
    printf("此二叉树的凹入法表示为:\n");
    OutBiTree(bt);
    printf("树状打印二叉树:\n");
    PrintTree(bt,1);
    return 0;
}

4. 调试分析

遇到的问题及解决方法
  • 算法思想比较复杂,通过举例子、一步一步画图拨开了云雾。
算法的时空分析

这里只有分支结构,没有循环结构,所以时间复杂度很低。同时也采取了链式存储,空间复杂度也不大。

实验结果

实验结果很不错,所有操作都能正常执行,并且自己加入了按树状打印二叉树,使得输出效果更加美观。
这是上面分析的例子的程序给出的输出。
在这里插入图片描述
下面这个例子大家也可以看看。
在这里插入图片描述
在这里插入图片描述

实验总结

比较复杂,但只要认真分析就没事,多多重复,百炼成钢!

最后附上完整的代码

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 255
//定义二叉树的链式存储结构,有三个域:数据域,左孩子域,右孩子域
typedef struct BiNode
{
    char data;
    struct BiNode *lc;
    struct BiNode *rc;
}BiTree;

//以广义表的形式创建二叉树
BiTree *CreatBiTreepre(char *str)
{
    BiTree *bt,*stack[MAXSIZE],*p=NULL;
    int top=-1,k,j=0;
    char ch;
    bt=NULL;
    ch=str[j];
    while(ch!='\0')
    {
        switch(ch)
        {
        case '(':
            {
                top++;
                stack[top]=p;
                k=1;
                break;
            }
        case ')':
            {
                top--;
                break;
            }
        case ',':
            {
                k=2;
                break;
            }
        default:
            {
                p=(BiTree *)malloc(sizeof(BiTree));
                p->data=ch;
                p->lc=p->rc=NULL;
                if(bt==NULL)
                {
                    bt=p;
                }
                else
                {
                    switch(k)
                    {
                    case 1:
                        {
                            stack[top]->lc=p;
                            break;
                        }
                    case 2:
                        {
                            stack[top]->rc=p;
                            break;
                        }
                    }
                }
            }
        }
        j++;
        ch=str[j];
    }
    return bt;//链式存储只用知道一个,后面顺藤摸瓜就都知道了
}

//采用凹入法输出二叉树
void OutBiTree(BiTree *bt)
{
    BiTree *stack[MAXSIZE],*p;
    int feature[MAXSIZE][2],top,n,i,width=4;
    char type;
    if(bt!=NULL)
    {
        top=1;
        stack[top]=bt;
        feature[top][0]=width;
        feature[top][1]=2;
        while(top>0)
        {
            p=stack[top];
            n=feature[top][0];
            switch(feature[top][1])
            {
            case 0:
                {
                    type='l';
                    break;
                }
            case 1:
                {
                    type='R';
                    break;
                }
            case 2:
                {
                    type='G';
                    break;
                }
            }
            for(i=1;i<=n;i++)
                printf(" ");
            printf("%c(%c)\n",p->data,type);
            top--;
            if(p->lc!=NULL)
            {
                top++;
                stack[top]=p->lc;
                feature[top][0]=n+width;
                feature[top][1]=0;
            }
            if(p->rc!=NULL)
            {
                top++;
                stack[top]=p->rc;
                feature[top][0]=n+width;
                feature[top][1]=1;
            }

        }
    }
}

void PrintTree(BiTree *bt,int nLayer)
{
    if(bt==NULL)
        return ;
    PrintTree(bt->rc,nLayer+1);
    for(int i=0;i<nLayer;i++)
        printf("  ");
    printf("%c\n",bt->data);
    PrintTree(bt->lc,nLayer+1);
}

int main()//(A(B(D,),C(,E)))   (A(B(D,E),C(F,G)))  ((((A),B)),(((),D),(E,F)))这个不是树
{
    BiTree *bt;
    char *gyb,str[MAXSIZE];
    int j=1;
    printf("-----------------------------------------------------");
    printf("\n            程序功能");
    printf("\n 1.将按照输入的二叉广义表表示字符串 ");
    printf("\n · 生成对应的二叉树链式结构。");
    printf("\n 2.输出二叉树的凹入法表示形式。");
    printf("\n · G--根 L--左孩子 R--右孩子");
    printf("\n 3.树状打印二叉树");
    printf("\n · 逆时针旋转90度显示二叉树");
    printf("\n * 输入示例:(A(B(D,),C(,E)))或(A(B(D,E),C(F,G)))");
    printf("\n-----------------------------------------------------\n");
    printf("请输入二叉树的广义表形式:\n");
    gyb=str;
    scanf("%s",str);
    bt =CreatBiTreepre(gyb);
    printf("二叉树建立成功!\n");
    printf("此二叉树的凹入法表示为:\n");
    OutBiTree(bt);
    printf("树状打印二叉树:\n");
    PrintTree(bt,1);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值