【数据结构6】二叉树的链式存储

文章目录

  • ⭐️写在前面的话⭐️
  • 二叉树的链式存储
    • 0、自定义
    • 1、构造空二叉树T
    • 2、销毁二叉树T
    • 3、构造一个按先序输入的二叉链表T
    • 4、按满二叉树的方式创建T2
    • 5、判断这棵树是否为空
    • 6、返回这棵树的深度(按先序遍历)
    • 7、返回这棵树的根结点
    • 8、先序遍历这棵树
    • 9、中序遍历这棵树
    • 10、后序遍历这棵树
    • 主函数
  • 程序源码
          • 运行截图

⭐️写在前面的话⭐️

博客主页: 程序员好冰
欢迎 【点赞 关注 收藏⭐️ 留言】
本文由 程序员好冰 原创,CSDN 首发!
入站时间: 2022 年 07 月 13 日
✉️ 是非不入松风耳,花落花开只读书。
推荐书籍:《Java编程思想》,《Java 核心技术卷》
参考在线编程网站:牛客网力扣
作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


二叉树的链式存储

0、自定义

#include 
#include 

/*二叉链表*/

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define  OVERFLOW -1

#define Nil '#'

#define MAX_SIZE 1024

typedef int Status;
typedef char ElemType;

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *LChild,*RChild;
}BiTNode,*BiTree;

1、构造空二叉树T

Status InitBiTree(BiTree *T)
{
    *T=NULL;
    return OK;
}

2、销毁二叉树T

Status DestoryBiTree(BiTree *T)
{
    if(*T){
        if((*T)->LChild){
            DestoryBiTree(&((*T)->LChild));
        }
        if((*T)->RChild){
            DestoryBiTree(&((*T)->RChild));
        }
        free(*T);
        *T=NULL;
    }
    return OK;
}

3、构造一个按先序输入的二叉链表T

解释为什么getchar()要放在前面

其他博主的代码都是将getchar()放在ch=getchar()后面,而我的是放前面;

原因是我的main主函数里面用到了scanf。

//返回一个当前所谓“根结点”的指针变量
void PreCreateBiTree(BiTree *T)
{
    ElemType ch;
    getchar();
    ch=getchar();
    //getchar();
    //printf("当前ch为:%c.\n",ch);//调试操作
    if(ch==Nil){
        *T=NULL;
    }else
    {
        *T=(BiTree)malloc(sizeof(BiTNode));
        (*T)->data=ch;
        PreCreateBiTree(&((*T)->LChild));
        PreCreateBiTree(&((*T)->RChild));
    }
}

4、按满二叉树的方式创建T2

    /*
    在建立过程中借助一个一维数组S[n] ,
    编号为i的结点保存在S[i]中,
    对每个结点,输入i、ch。
    */
//由这种方法创建出来的树T2
Status CreateBiTree2(BiTree T2)
{
    BiTNode *p;//指向当前需要处理的结点
    BiTNode *arr[MAX_SIZE];//存放输入的结点
    char ch;
    int i,j;
    while(1){
        scanf("%d",&i);//从1开始
        getchar();
        if(i==0){
            break;//0号位置不存
        }
        if(i!=0){
            ch=getchar();
            if(ch==Nil){
                continue;
            }
            p=(BiTNode*)malloc(sizeof(BiTNode));
            p->data=ch;
            p->LChild=NULL;//清空操作
            p->RChild=NULL;
            arr[i]=p;
            if(i==1){
                T2=p;//i=1说明为树的根结点
            }
            if(i!=1){
                //根据二叉树的性质
                j=i/2;//为当前结点的父节点
                if(i%2==0){
                    //为j对应的左节点
                    arr[j]->LChild=p;
                }
                if(i%2!=0){
                    //为j对应的右结点
                    arr[j]->RChild=p;
                }
            }
        }
    }
    PreOrderTraverse(T2);
    return OK;
}

5、判断这棵树是否为空

Status BiTreeEmpty(BiTree T)
{
    if(T){
        return FALSE;
    }
    return TRUE;
}

6、返回这棵树的深度(按先序遍历)

int BiTreeDepth(BiTree T)
{
    int left,right;//分别记录每棵左右子树的深度
    if(BiTreeEmpty(T)==TRUE){
        return 0;
    }
    if(T->LChild){
        left=BiTreeDepth(T->LChild);
    }else
    {
        left=0;
    }
    if(T->RChild){
        right=BiTreeDepth(T->RChild);
    }else
    {
        right=0;
    }
    return left>right?left+1:right+1;//加上每棵子树的根结点
}

7、返回这棵树的根结点

ElemType Root(BiTree T)
{
    if(!BiTreeEmpty(T)){
        return T->data;
    }
    return Nil;
}

8、先序遍历这棵树

void PreOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    printf("%c  ",T->data);
    PreOrderTraverse(T->LChild);
    PreOrderTraverse(T->RChild);
}

9、中序遍历这棵树

void InOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    InOrderTraverse(T->LChild);
    printf("%c  ",T->data);
    InOrderTraverse(T->RChild);
}

10、后序遍历这棵树

void PostOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    PostOrderTraverse(T->LChild);
    PostOrderTraverse(T->RChild);
    printf("%c  ",T->data);
}

主函数

int main()
{
    printf("请继续操作...\n");
    BiTree T;
    BiTree T2;
    int input;
    while(1){
        printf("\n---------------------------------\n");
        printf("1、构造空二叉树T.\n");
        printf("2、销毁二叉树T.\n");
        printf("3、构造一个按先序输入的二叉链表T.\n");
        printf("4、按满二叉树的方式创建T2.\n");
        printf("5、判断这棵树是否为空.\n");
        printf("6、返回这棵树的深度(按先序遍历).\n");
        printf("7、返回这棵树的根结点.\n");
        printf("8、先序遍历这棵树.\n");
        printf("9、中序遍历这棵树.\n");
        printf("10、后序遍历这棵树.\n");
        printf("---------------------------------\n");
        printf("\n");
        printf("请输入对应操作的序号:");
        scanf("%d",&input);
        switch(input)
        {
        case 1:
            if(InitBiTree(&T)){
                printf("二叉链表初始化成功.\n");
            }
            break;
        case 2:
            if(DestoryBiTree(&T)){
                printf("二叉链表销毁成功.\n");
            }
            break;
        case 3:
            printf("按先序方式创建这棵树T:\n");
            PreCreateBiTree(&T);
            break;
        case 4:
            printf("请按满二叉树方式创建这棵树T2:\n");
            printf("(依次输入对应结点的序号,回车后输入结点的值).\n");
            if(CreateBiTree2(T2)){
                printf("\n树T2创建成功.\n");
            }
            break;
        case 5:
            if(BiTreeEmpty==TRUE){
                printf("这棵树为空.\n");
            }else
            {
                printf("这棵树不为空.\n");
            }
            break;
        case 6:
            printf("这棵树的深度为:%d.\n",BiTreeDepth(T));
            break;
        case 7:
            printf("当前树的根结点为:%c.\n",Root(T));
            break;
        case 8:
            printf("树T先序遍历的结果为(递归方法):\n");
            PreOrderTraverse(T);
            break;
        case 9:
            printf("树T中序遍历的结果为(递归方法):\n");
            InOrderTraverse(T);
            break;
        case 10:
            printf("树T后序遍历的结果为(递归方法):\n");
            PostOrderTraverse(T);
            break;
        default:
            printf("输入的序号有误,请重新操作...\n");
            break;
        }
    }
    return 0;
}

程序源码

运行截图

【数据结构6】二叉树的链式存储_第1张图片

#include 
#include 

/*二叉链表*/

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define  OVERFLOW -1

#define Nil '#'

#define MAX_SIZE 1024

typedef int Status;
typedef char ElemType;

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *LChild,*RChild;
}BiTNode,*BiTree;

//1、构造空二叉树T
Status InitBiTree(BiTree *T)
{
    *T=NULL;
    return OK;
}

//2、销毁二叉树T
Status DestoryBiTree(BiTree *T)
{
    if(*T){
        if((*T)->LChild){
            DestoryBiTree(&((*T)->LChild));
        }
        if((*T)->RChild){
            DestoryBiTree(&((*T)->RChild));
        }
        free(*T);
        *T=NULL;
    }
    return OK;
}

//3、构造一个按先序输入的二叉链表T
//返回一个当前所谓“根结点”的指针变量
void PreCreateBiTree(BiTree *T)
{
    ElemType ch;
    getchar();
    ch=getchar();
    //getchar();
    //printf("当前ch为:%c.\n",ch);//调试操作
    if(ch==Nil){
        *T=NULL;
    }else
    {
        *T=(BiTree)malloc(sizeof(BiTNode));
        (*T)->data=ch;
        PreCreateBiTree(&((*T)->LChild));
        PreCreateBiTree(&((*T)->RChild));
    }
}

//4、按满二叉树的方式创建T2
    /*
    在建立过程中借助一个一维数组S[n] ,
    编号为i的结点保存在S[i]中,
    对每个结点,输入i、ch。
    */
//由这种方法创建出来的树T2
Status CreateBiTree2(BiTree T2)
{
    BiTNode *p;//指向当前需要处理的结点
    BiTNode *arr[MAX_SIZE];//存放输入的结点
    char ch;
    int i,j;
    while(1){
        scanf("%d",&i);//从1开始
        getchar();
        if(i==0){
            break;//0号位置不存
        }
        if(i!=0){
            ch=getchar();
            if(ch==Nil){
                continue;
            }
            p=(BiTNode*)malloc(sizeof(BiTNode));
            p->data=ch;
            p->LChild=NULL;//清空操作
            p->RChild=NULL;
            arr[i]=p;
            if(i==1){
                T2=p;//i=1说明为树的根结点
            }
            if(i!=1){
                //根据二叉树的性质
                j=i/2;//为当前结点的父节点
                if(i%2==0){
                    //为j对应的左节点
                    arr[j]->LChild=p;
                }
                if(i%2!=0){
                    //为j对应的右结点
                    arr[j]->RChild=p;
                }
            }
        }
    }
    PreOrderTraverse(T2);
    return OK;
}

//5、判断这棵树是否为空
Status BiTreeEmpty(BiTree T)
{
    if(T){
        return FALSE;
    }
    return TRUE;
}

//6、返回这棵树的深度(按先序遍历)
int BiTreeDepth(BiTree T)
{
    int left,right;//分别记录每棵左右子树的深度
    if(BiTreeEmpty(T)==TRUE){
        return 0;
    }
    if(T->LChild){
        left=BiTreeDepth(T->LChild);
    }else
    {
        left=0;
    }
    if(T->RChild){
        right=BiTreeDepth(T->RChild);
    }else
    {
        right=0;
    }
    return left>right?left+1:right+1;//加上每棵子树的根结点
}

//7、返回这棵树的根结点
ElemType Root(BiTree T)
{
    if(!BiTreeEmpty(T)){
        return T->data;
    }
    return Nil;
}

//8、先序遍历这棵树
void PreOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    printf("%c  ",T->data);
    PreOrderTraverse(T->LChild);
    PreOrderTraverse(T->RChild);
}

//9、中序遍历这棵树
void InOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    InOrderTraverse(T->LChild);
    printf("%c  ",T->data);
    InOrderTraverse(T->RChild);
}

//10、后序遍历这棵树
void PostOrderTraverse(BiTree T)
{
    if(T==NULL){
        return ;
    }
    PostOrderTraverse(T->LChild);
    PostOrderTraverse(T->RChild);
    printf("%c  ",T->data);
}

int main()
{
    printf("请继续操作...\n");
    BiTree T;
    BiTree T2;
    int input;
    while(1){
        printf("\n---------------------------------\n");
        printf("1、构造空二叉树T.\n");
        printf("2、销毁二叉树T.\n");
        printf("3、构造一个按先序输入的二叉链表T.\n");
        printf("4、按满二叉树的方式创建T2.\n");
        printf("5、判断这棵树是否为空.\n");
        printf("6、返回这棵树的深度(按先序遍历).\n");
        printf("7、返回这棵树的根结点.\n");
        printf("8、先序遍历这棵树.\n");
        printf("9、中序遍历这棵树.\n");
        printf("10、后序遍历这棵树.\n");
        printf("---------------------------------\n");
        printf("\n");
        printf("请输入对应操作的序号:");
        scanf("%d",&input);
        switch(input)
        {
        case 1:
            if(InitBiTree(&T)){
                printf("二叉链表初始化成功.\n");
            }
            break;
        case 2:
            if(DestoryBiTree(&T)){
                printf("二叉链表销毁成功.\n");
            }
            break;
        case 3:
            printf("按先序方式创建这棵树T:\n");
            PreCreateBiTree(&T);
            break;
        case 4:
            printf("请按满二叉树方式创建这棵树T2:\n");
            printf("(依次输入对应结点的序号,回车后输入结点的值).\n");
            if(CreateBiTree2(T2)){
                printf("\n树T2创建成功.\n");
            }
            break;
        case 5:
            if(BiTreeEmpty==TRUE){
                printf("这棵树为空.\n");
            }else
            {
                printf("这棵树不为空.\n");
            }
            break;
        case 6:
            printf("这棵树的深度为:%d.\n",BiTreeDepth(T));
            break;
        case 7:
            printf("当前树的根结点为:%c.\n",Root(T));
            break;
        case 8:
            printf("树T先序遍历的结果为(递归方法):\n");
            PreOrderTraverse(T);
            break;
        case 9:
            printf("树T中序遍历的结果为(递归方法):\n");
            InOrderTraverse(T);
            break;
        case 10:
            printf("树T后序遍历的结果为(递归方法):\n");
            PostOrderTraverse(T);
            break;
        default:
            printf("输入的序号有误,请重新操作...\n");
            break;
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构,链表)