二叉树——课上练(顺序存储结构)

写完作业后记得给我点个赞呗~

目录

答案代码总览

主函数

第1关:创建顺序结构的二叉树

第2关:二叉树基本操作

 第3关:二叉树的层序遍历

 第4关:二叉树的先序遍历


答案代码总览

我修改了题目结构体的定义,以符合我的编程习惯

// Created by Mr.Chen on 2023/10/14.
#include <stdio.h>
#include <stdlib.h>

typedef char DataType;

//定义顺序存储结构
typedef struct node
{
    int maxNum; //最多可存储元素的个数
    int n; //当前元素个数
    DataType* data; //存储元素的数组
}node;

typedef node* seqBiTree;

/*辅助功能:逐个输出顺序表的元素,元素之间以空格为界*/
void printTree(seqBiTree T)
{
    for (int i = 0; i < T->n ; ++i)
    {
        if (T->data[i] == '#')
            putchar(' '); //答案格式如此,没办法
        else
        {
            putchar(T->data[i]);
        }
        //元素之间以空格为界
        putchar(' ');
    }
}

/*第一关
* 形参m: 顺序表的最多可存储元素的个数
* 返回值:顺序存储的二叉树
*/
seqBiTree createSeqTree(int m)
{
    //按层次遍历的顺序输入二叉树中的结点元素值,依顺序存储各结点元素。
    //题目已经给好了层序遍历的顺序,我们只需要按部就班地读入即可

    //定义并创建一个顺序二叉树
    seqBiTree T = (seqBiTree) malloc(sizeof(struct node));

    //初始化T,并为数组分配存储空间
    T->maxNum = m;
    T->n  = 0;
    T->data = (DataType*) malloc(sizeof (DataType) * m);

    //读入元素
    int i = 0;
    DataType ch = getchar();
    while (ch != '\n')
    {
        T->data[T->n ] = ch;
        T->n ++;
        ch = getchar();
    }

    return T;
}

/*第二关,返回二叉树的根结点的值,若二叉树为空,则返回#*/
char root(seqBiTree T)
{

    if(T->n  == 0)
        return '#';  //当前元素个数为0即二叉树为空
    else
        return T->data[0]; //第一个元素即是根节点的值
}

/*第二关,求二叉树T中指定结点ch的双亲结点,返回值是双亲结点的下标,若双亲不存在,则返回-1*/
int parent(seqBiTree T ,char ch)
{
    for (int i = 0; i < T->n ; ++i)
    {
        //遍历数组,找结点ch
        if (T->data[i] == ch)
        {
            /*完全二叉树的性质:对任意下标为i的结点,
              若i = 0,则它为根结点,没有父结点(没有双亲)
              若i > 0,则它的父节点下标为(i-1)/2  */
            if (i == 0)
                return -1;
            else
                return (i - 1) / 2;
        }
    }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
 }
/*第二关,求二叉树T中指定结点ch的左孩子的下标,若左孩子不存在,则返回-1*/
    int leftChild(seqBiTree T, char ch) {
        for (int i = 0; i < T->n ; ++i) {
            //遍历数组,找结点ch
            if (T->data[i] == ch) {
                /*完全二叉树的性质:对任意下标为i的结点(从0到n-1进行编号),
                  若2i + 1 <= n - 1,则它的左结点下标为2i + 1
                  否则它没有左结点*/
                //将‘#’纳入后,T可视为完全二叉树;但返回下标时要排除'#'.
                if ((2*i + 1) <= T->n  - 1 && T->data[2*i+1] != '#')
                    return 2*i + 1;
                else
                    return -1;
            }
        }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
    }

/*第二关,求二叉树T中指定结点ch的右孩子的下标,若右孩子不存在,则返回-1*/
    int rightChild(seqBiTree T, char ch) {
        for (int i = 0; i < T->n ; ++i) {
            //遍历数组,找结点ch
            if (T->data[i] == ch) {
                /*完全二叉树的性质:对任意下标为i的结点(从0到n-1进行编号),
                  若2i + 2 <= n - 1,则它的右结点下标为2i + 2
                  否则它没有右结点  */
                if ((2*i + 2) <= T->n - 1 && T->data[2*i+2] != '#')
                    return 2*i + 2;
                else
                    return -1;
            }
        }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
    }

/*第三关:层序遍历二叉树,输出遍历得到的结点,结点之间不需要空格*/
    void levelOrder(seqBiTree T)
    {
        //输入时已经是层序遍历的顺序,所以按数组顺序输出即是层序遍历啦
        for (int i = 0; i < T->n; ++i)
        {
            if(T->data[i] != '#')
                putchar(T->data[i]);
        }
    }

/*第四关:先序遍历二叉树,输出遍历得到的结点,结点之间不需要空格
* 形参root: 二叉树的根所在的下标
*/
    void preOrder(seqBiTree T, int root)
    {
        //先序遍历、中序遍历、后序遍历所用的算法思想的都是递归
        if(root >= T->n || T->data[root] == '#')
            return;
        putchar(T->data[root]);    //打印输出当前结点
        preOrder(T,2*root + 1);    //遍历左结点
        preOrder(T,2*root + 2);    //遍历右结点
    }

    int main(void)
    {
        int m;//顺序表可存放最多的元素个数
        scanf("%d", &m);
        seqBiTree T = createSeqTree(m);

        printTree(T); //测评第一关时,把本行代码放开

        printf("%c\n", root(T)); //  测评第二关时,把该代码块放开
        printf("%d\n", leftChild(T, 'A'));
        printf("%d\n", rightChild(T, 'A'));
        printf("%d\n", parent(T, 'A'));*/

        levelOrder(T); //测评第三关时,把本行代码放开

        preOrder(T,0); //测评第四关时,把本行代码放开
        return 0;
    }

主函数

    int main(void)
    {
        int m;//顺序表可存放最多的元素个数
        scanf("%d", &m);
        seqBiTree T = createSeqTree(m);

        printTree(T); //测评第一关时,把本行代码放开

        printf("%c\n", root(T)); //  测评第二关时,把该代码块放开
        printf("%d\n", leftChild(T, 'A'));
        printf("%d\n", rightChild(T, 'A'));
        printf("%d\n", parent(T, 'A'));*/

        levelOrder(T); //测评第三关时,把本行代码放开

        preOrder(T,0); //测评第四关时,把本行代码放开
        return 0;
    }

第1关:创建顺序结构的二叉树

本关任务:输入二叉树的结点的数据,创建一个顺序结构存储二叉树 二叉树的数据为字符类型,输入‘#’表示该结点为空.

/*辅助功能:逐个输出顺序表的元素,元素之间以空格为界*/
void printTree(seqBiTree T)
{
    for (int i = 0; i < T->n ; ++i)
    {
        if (T->data[i] == '#')
            putchar(' '); //答案格式如此,没办法
        else
        {
            putchar(T->data[i]);
        }
        //元素之间以空格为界
        putchar(' ');
    }
}

/*第一关
* 形参m: 顺序表的最多可存储元素的个数
* 返回值:顺序存储的二叉树
*/
seqBiTree createSeqTree(int m)
{
    //按层次遍历的顺序输入二叉树中的结点元素值,依顺序存储各结点元素。
    //题目已经给好了层序遍历的顺序,我们只需要按部就班地读入即可

    //定义并创建一个顺序二叉树
    seqBiTree T = (seqBiTree) malloc(sizeof(struct node));

    //初始化T,并为数组分配存储空间
    T->maxNum = m;
    T->n  = 0;
    T->data = (DataType*) malloc(sizeof (DataType) * m);

    //读入元素
    int i = 0;
    DataType ch = getchar();
    while (ch != '\n')
    {
        T->data[T->n ] = ch;
        T->n ++;
        ch = getchar();
    }

    return T;
}

第2关:二叉树基本操作

本关任务:完成函数,能分别求出某二叉树的根、某个结点的双亲、左孩子、右孩子

/*第二关,返回二叉树的根结点的值,若二叉树为空,则返回#*/
char root(seqBiTree T)
{

    if(T->n  == 0)
        return '#';  //当前元素个数为0即二叉树为空
    else
        return T->data[0]; //第一个元素即是根节点的值
}

/*第二关,求二叉树T中指定结点ch的双亲结点,返回值是双亲结点的下标,若双亲不存在,则返回-1*/
int parent(seqBiTree T ,char ch)
{
    for (int i = 0; i < T->n ; ++i)
    {
        //遍历数组,找结点ch
        if (T->data[i] == ch)
        {
            /*完全二叉树的性质:对任意下标为i的结点,
              若i = 0,则它为根结点,没有父结点(没有双亲)
              若i > 0,则它的父节点下标为(i-1)/2  */
            if (i == 0)
                return -1;
            else
                return (i - 1) / 2;
        }
    }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
 }

/*第二关,求二叉树T中指定结点ch的左孩子的下标,若左孩子不存在,则返回-1*/
    int leftChild(seqBiTree T, char ch) {
        for (int i = 0; i < T->n ; ++i) {
            //遍历数组,找结点ch
            if (T->data[i] == ch) {
                /*完全二叉树的性质:对任意下标为i的结点(从0到n-1进行编号),
                  若2i + 1 <= n - 1,则它的左结点下标为2i + 1
                  否则它没有左结点*/
                //将‘#’纳入后,T可视为完全二叉树;但返回下标时要排除'#'.
                if ((2*i + 1) <= T->n  - 1 && T->data[2*i+1] != '#')
                    return 2*i + 1;
                else
                    return -1;
            }
        }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
    }

/*第二关,求二叉树T中指定结点ch的右孩子的下标,若右孩子不存在,则返回-1*/
    int rightChild(seqBiTree T, char ch) {
        for (int i = 0; i < T->n ; ++i) {
            //遍历数组,找结点ch
            if (T->data[i] == ch) {
                /*完全二叉树的性质:对任意下标为i的结点(从0到n-1进行编号),
                  若2i + 2 <= n - 1,则它的右结点下标为2i + 2
                  否则它没有右结点  */
                if ((2*i + 2) <= T->n - 1 && T->data[2*i+2] != '#')
                    return 2*i + 2;
                else
                    return -1;
            }
        }
        //树为空(T->n ==0)||结点ch不存在
        return -1;
    }

 第3关:二叉树的层序遍历

本关任务:完成二叉树的层序遍历算法

/*第三关:层序遍历二叉树,输出遍历得到的结点,结点之间不需要空格*/
    void levelOrder(seqBiTree T)
    {
        //输入时已经是层序遍历的顺序,所以按数组顺序输出即是层序遍历啦
        for (int i = 0; i < T->n; ++i)
        {
            if(T->data[i] != '#')
                putchar(T->data[i]);
        }
    }

 第4关:二叉树的先序遍历

本关任务:完成遍历二叉树的函数

/*第四关:先序遍历二叉树,输出遍历得到的结点,结点之间不需要空格
* 形参root: 二叉树的根所在的下标
*/
    void preOrder(seqBiTree T, int root)
    {
        //先序遍历、中序遍历、后序遍历所用的算法思想的都是递归
        if(root >= T->n || T->data[root] == '#')
            return;
        putchar(T->data[root]);    //打印输出当前结点
        preOrder(T,2*root + 1);    //遍历左结点
        preOrder(T,2*root + 2);    //遍历右结点
    }

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
算法与数据结构它们分别涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
算法与数据结构它们分别涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值