36.树与二叉树练习(2)(王道第5章综合练习)

news2025/1/31 3:15:46

试题1(王道5.3.3节第16题):

设计算法将二叉树的叶结点按从左到右的顺序连成单链表,连接时使用叶结点的右指针域存放单链表指针。

借助遍历算法完成:

//根据二叉树层次遍历序列构造单链表
void LevelOrdertoLinkList(BiTree &T){
    Queue q;
    InitQueue(q);
    BiTree p = T;
    BiTree pre = NULL;
    InsertQueue(q, p);
    while(!IsQueueEmpty(q)){
        p = DeleteQueue(q, p);
        if(p->lchild!=NULL)
            InsertQueue(q, p->lchild);
        if(p->rchild!=NULL)
            InsertQueue(q, p->rchild);
        if(pre!=NULL){
            pre->lchild = NULL;
            pre->rchild = p;
        }
        pre = p;  
    }
}

//单链表打印函数,作为验证
void PrintLinkTree(BiTree T){
    BiTree p = T;
    while(p!=NULL){
        printf("%c", p->data);
        p = p->rchild;
    }
}

int main(){
    BiTree T;
    printf("输入二叉树的前序序列,#代表空子树:\n");
    CreateBiTree(T);
    printf("二叉树创建成功!\n");
    LevelOrdertoLinkList(T);
    PrintLinkTree(T);  //打印生成的单链表
    return 0;
}

输出:

输入二叉树的前序序列,#代表空子树:
ABDF###E##C##
二叉树创建成功!
ABCDEF

试题2(王道5.3.3节第17题):

设计算法判断两棵二叉树是否相似。

//判断两个二叉树是否相似
bool Similar(BiTree T1,BiTree T2){
    if(T1 != NULL&&T2 == NULL){
        return false;
    }
    else if(T1 == NULL&&T2 != NULL){
        return false;
    }
    else if(T1 == NULL&&T2 == NULL)
        return true;
    else{
        return Similar(T1->lchild, T2->lchild) && Similar(T1->rchild, T2->rchild);
    }
}

int main(){
    BiTree T1;
    printf("输入二叉树T1的前序序列,#代表空子树:\n");
    CreateBiTree(T1);
    printf("二叉树T1创建成功!\n");

    while (getchar() != '\n');  //清空缓存区

    BiTree T2;
    printf("输入二叉树T2的前序序列,#代表空子树:\n");
    CreateBiTree(T2);
    printf("二叉树T2创建成功!\n");

    printf("%d", Similar(T1, T2));
    return 0;
}

输出:

输入二叉树T1的前序序列,#代表空子树:
AB##C##
二叉树T1创建成功!
输入二叉树T2的前序序列,#代表空子树:
DE##F##
二叉树T2创建成功!
1

试题3(王道5.3.3节第18题):

写出在中序线索二叉树中查找指定结点在后序的前驱结点的算法。

我们先把二叉线索树写出来:

//二叉线索树的结构体定义
typedef struct BiTNode{
    ElemType data;  //数据域
    BiTNode *lchild;  //指向左子树根节点的指针
	BiTNode *rchild;  //指向右子树根节点的指针
    int ltag, rtag;
}BiTNode, *BiTree;

//建立中序线索二叉树
void InThread(BiTree &T,BiTree &pre){
    BiTree p = T;
    if(p!=NULL){
        InThread(p->lchild,pre);
        if(pre!=NULL && pre->rchild==NULL){
            pre->rchild = p;
            pre->rtag = 1;
        }
        if(p->lchild == NULL){
            p->lchild = pre;
            p->ltag = 1;
        }
        pre = p;
        InThread(p->rchild,pre);
    }
}

BiTree FirstNode(BiTree T){  //获取中序序列的第一个结点
    BiTree p = T;
    while(p->ltag == 0){
        p = p->lchild;
    }
    return p;
}

BiTree NextNode(BiTree p){  //求解结点在中序序列下的下一个结点
    if(p->rtag = 0)
        return FirstNode(p->rchild);
    else
        return p->rchild;
}

BiTree LastNode(BiTree p){  //求解结点在中序序列下的上一个结点
    if(p->ltag =0)
        return FirstNode(p->lchild);
    else
        return p->lchild;
}

//有了前两个函数我们就可以在中序线索二叉树中输出中序遍历序列
void InorderTraverse3(BiTree T){
    BiTree p = FirstNode(T);
    printf("%c", p->data);
    while(p->rchild!=NULL){
        p = NextNode(p);
        printf("%c", p->data);
    }
}

int main(){
    BiTree T;
    BiTree p = NULL;
    printf("输入二叉树的前序序列,#代表空子树:\n");
    CreateBiTree(T);
    printf("二叉树创建成功!\n");
    InThread(T,p);
    p = FirstNode(T);
    printf("二叉树中序序列的第一个结点是:%c\n", p->data);
    printf("二叉树的中序遍历序列是:");
    InorderTraverse3(T);
    return 0;
}

输出:

输入二叉树的前序序列,#代表空子树:
ABDF###E##C##
二叉树创建成功!
二叉树中序序列的第一个结点是:F
二叉树的中序遍历序列是:FDBEAC

分以下几种情况:

(1)结点有右孩子——右孩子就是后序遍历的前驱结点;

(2)结点只有左孩子——左孩子是后序遍历的前驱结点;

(3)结点没有左右孩子——找中序遍历前驱结点的左孩子结点,找不到就继续往前直到找到有左孩子结点,或者就是第一个结点(左孩子指针为空)返回NULL。

//求在中序线索二叉树中查找指定结点后序遍历的前驱
BiTree FindPast(BiTree p){
    if(p->rtag == 0 && p->rchild != NULL)
        return p->rchild;
    else if(p->ltag == 0)
        return p->lchild;
    else if(p->ltag == 1 && p->lchild == NULL)
        return NULL;
    else{  //叶子结点
        while(p->ltag == 1 && p->lchild != NULL){
            p = p->lchild;  //回溯
        }
        if(p->ltag == 0)
            return p->lchild;
        else
            return NULL;
    }
}

int main(){
    BiTree T;
    BiTree p = NULL;
    printf("输入二叉树的前序序列,#代表空子树:\n");
    CreateBiTree(T);
    printf("二叉树创建成功!\n");
    printf("二叉树的中序遍历序列是:");
    InOrderTraverse(T);
    printf("\n");
    printf("二叉树的后序遍历序列是:");
    PostOrderTraverse(T);
    printf("\n");
    InThread(T,p);  //线索化
    BiTree q = T->rchild;  //这行代码找测试结点,实际需要根据用例修改
    printf("结点%c的后序遍历序列的前驱结点是:%c", q->data, FindPast(q)->data);
    return 0;
}

输出:

输入二叉树的前序序列,#代表空子树:
A#B#C##
二叉树创建成功!
二叉树的中序遍历序列是:ABC
二叉树的后序遍历序列是:CBA
结点B的后序遍历序列的前驱结点是:C

输入二叉树的前序序列,#代表空子树:
AB##C##
二叉树创建成功!
二叉树的中序遍历序列是:BAC
二叉树的后序遍历序列是:BCA
结点C的后序遍历序列的前驱结点是:B

试题4(2014年统考真题):

直接递归:

//前序序列建立二叉树
void CreateBiTree(BiTree &T){
    char ch;
    scanf("%c", &ch);
    if (ch == '#')
        T = NULL;  //保证是叶结点
    else{
        T = (BiTree)malloc(sizeof(BiTNode));
        T->data = (int)ch;  //生成结点(这里偷个懒直接强制转换)
        printf("%d", T->data);
        CreateBiTree(T->lchild);  //构造左子树
        CreateBiTree(T->rchild);  //构造右子树    
    }
}


int WPLBiTree(BiTree T,int depth){
    if(T==NULL)
        return 0;
    else
        return T->data * depth + WPLBiTree(T->lchild, depth + 1) + WPLBiTree(T->rchild, depth + 1);
}

int main(){
    BiTree T;
    CreateBiTree(T);
    printf("二叉树建立成功!");
    printf("二叉树的带权路径长度是:%d", WPLBiTree(T,1));
    return 0;
}

输出:

32##4##
515052二叉树建立成功!二叉树的带权路径长度是:255

试题5(2017年统考真题):

此题很显然要利用到二叉树的中序遍历算法。除根结点和叶结点外,遍历到其他结点时在遍历左子树前加上左括号,遍历完右子树后加上右括号。

//本算法给表达式加括号
void InOrderExpression(BiTree T){
    if(T!=NULL){
        if((T->lchild!=NULL||T->rchild!=NULL))
            printf("(");
        InOrderExpression(T->lchild);
        printf("%c", T->data);
        InOrderExpression(T->rchild);
        if((T->lchild!=NULL||T->rchild!=NULL))
            printf(")");
    }     
}

int main(){
    BiTree T;
    printf("输入中缀表达式二叉树的前序序列:");
    CreateBiTree(T);
    printf("二叉树建立成功!\n");
    printf("二叉树的中序序列是:");
    InOrderTraverse(T);
    printf("\n");
    printf("二叉树的中序序列(加括号)是:");
    InOrderExpression(T);
    printf("\n");
    return 0;
}

输出:

输入中缀表达式二叉树的前序序列:*+A##B##*C##-#D##
二叉树建立成功!
二叉树的中序序列是:A+B*C*-D
二叉树的中序序列(加括号)是:((A+B)*(C*(-D)))

试题6(王道5.4.4节第4题):

编程求以孩子兄弟表示法存储的森林的叶子结点数。

分析:二叉树中(1)叶子结点(2)只有右孩子没有左孩子的结点是原森林的叶子结点。随便一种遍历方式,对遍历的结点加以判断即可。

//求森林的叶子结点数
int num = 0;
int Numofleafknots(BiTree T){
	if (T!=NULL){
		Numofleafknots(T->lchild);
        if(T->lchild==NULL&&T->rchild!=NULL)
            num = num + 1;
        else if(T->lchild==NULL&&T->rchild==NULL)
            num = num + 1;
        else{

        }
        Numofleafknots(T->rchild);
	}
    return num;
}

int main(){
    BiTree T;
    printf("输入森林对应二叉树的前序序列:");
    CreateBiTree(T);
    printf("二叉树建立成功!\n");
    printf("此森林的叶子结点数是:%d",Numofleafknots(T));
    return 0;
}

输出(这里以书上图5.17做验证):

输入森林对应二叉树的前序序列:AB#C#D##EF##GH#I###
二叉树建立成功!
此森林的叶子结点数是:6

试题7(王道5.4.4节第5题):

以孩子兄弟链表为存储结构,请设计递归算法求树的深度。

从树转化成二叉树:左孩子向下走相当于深度+1,右孩子向下走相当于访问同深度兄弟结点。

//求森林的叶子结点数
int DepthofForest(BiTree T){
	if(T==NULL)
        return 0;
    else{
        return 1 + DepthofForest(T->lchild) > DepthofForest(T->rchild) ? 1 + DepthofForest(T->lchild) : DepthofForest(T->rchild);
    }
}

int main(){
    BiTree T;
    printf("输入树对应二叉树的前序序列:");
    CreateBiTree(T);
    printf("二叉树建立成功!\n");
    printf("此树的深度是:%d",DepthofForest(T));
    return 0;
}

输出(这里以书上图5.14,图5.15做验证):

输入森林对应二叉树的前序序列:RAD#E##B#CFG#H#K#####
二叉树建立成功!
此树的深度是:4

试题8(王道5.4.4节第6题):

已知一棵树的层次序列和每个结点的度,编写算法构造此树的孩子-兄弟链表。

此题借助辅助空间会好做很多:

//构造数组存放层次序列和度的信息
struct Node{
    char data;
    int degree;
} a[10] = {{'R', 3}, {'A', 2}, {'B', 0}, {'C', 1}, {'D', 0}, {'E', 0}, {'F', 3}, {'G', 0}, {'H', 0}, {'K', 0}};  //仍然以图5.14,5.15为例

BiTree BuildBiTree(Node a[]){
    int x = 0;  //记录当前结点的孩子
    BiTree bitree[10];
    for (int i = 0; i < 10;i++){
        bitree[i] = (BiTree)malloc(sizeof(BiTNode));
        bitree[i]->data = a[i].data;
        bitree[i]->lchild = NULL;  //初始全为空
        bitree[i]->rchild = NULL;
    }  //这一步生成了10个结点
    for (int i = 0; i < 10;i++){
        for (int j = 0; j < a[i].degree;j++){
            x = x + 1;  //此时x指向i的第一个孩子
            if(j==0)
                bitree[i]->lchild = bitree[x];
            else
                bitree[x - 1]->rchild = bitree[x];
        }
    }
    return bitree[0];
}

int main(){
    printf("此树的深度是:%d\n",DepthofForest(BuildBiTree(a)));
    printf("此树对应的二叉树深度是:%d", Depth(BuildBiTree(a)));
    return 0;
}

输出:

此树的深度是:4
此树对应的二叉树深度是:8

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1094213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt事件传播机制 day8

Qt事件传播机制 day8 事件的接受和忽略 当空间忽略事件时&#xff0c;事件会继续往上传播&#xff0c;这里的传播指传播给父组件QEvent有accept()函数与ignore()函数 accept()&#xff1a;本组件处理该事件&#xff0c;这个事件就不会被继续传播给其父组件ignore()&#xff1…

spring boot Rabbit高级教程

消息可靠性 生产者重试机制 首先第一种情况&#xff0c;就是生产者发送消息时&#xff0c;出现了网络故障&#xff0c;导致与MQ的连接中断。 为了解决这个问题&#xff0c;SpringAMQP提供的消息发送时的重试机制。即&#xff1a;当RabbitTemplate与MQ连接超时后&#xff0c;…

分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测

分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测 目录 分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现WOA-CNN-LSTM-Attention数据分类预测&#xff0c;运行环境Matlab2021b及以…

Marin说PCB之BGA焊盘削焊盘带来的焊接问题和解决办法

每周日上午10点钟都是小编最开心的时间了&#xff0c;这个点是斗破苍穹播出的时间。小编我从萧炎从这个动漫开播到现在都追了好多年了&#xff0c;强烈推荐喜欢这个小说的可以看这个动漫&#xff0c;拍的还不错&#xff0c;只是萧炎的配音不再是张沛老师了&#xff0c;有点可惜…

Python实验三

1&#xff1a;编程统计英文句子中的单词出现的次数。 要求&#xff1a;输出结果为按照单词在句子中出现的次数降序排列。 提示&#xff1a;用split&#xff08;&#xff09;拆分字符串 # 1&#xff1a;编程统计英文句子中的单词出现的次数。 # 要求&#xff1a;输出结果为按照…

Java 继承与实现

一、继承&#xff08;extends&#xff09; 1.1 继承概念 继承是面向对象的基本特征&#xff0c;它允许子类继承父类的特征和行为&#xff0c;以提高代码的复用率和维护性等。下面一张图生动地展示了继承和类之间的关系&#xff1a; 继承图 上图中&#xff0c;“动物”、“食草…

【Vue面试题二十一】、Vue中的过滤器了解吗?过滤器的应用场景有哪些?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;Vue中的过滤器了解吗&am…

成为数据分析师要具备什么能力——功法篇(上)

这篇文章适合做了一段时间数据分析工作&#xff0c;开始思考怎么继续提升自己的分析师、运营或者是实习了一段时间的同学&#xff0c;这时的你也许会想几个问题&#xff1a; 为什么我做出来的分析总觉得没有别人的那么高级&#xff1f; 老板为什么总说我的分析“太浅了”&#…

spyder切换conda环境(成功测试)

今天第一次把这个anaconda中配套的spyder的切换环境尝试成功了&#xff0c;特地记录一下 首先明确一点我使用的最新的anaconda的版本是 spyder已经是版本5了&#xff0c;之前的4版本总是出现各种错误 Step1 切换python interpreter 环境是可以直接识别的&#xff0c;不需要…

2023-2024-1 for循环-1(15-38)

7-15 输出闰年 输出21世纪中截止某个年份以来的所有闰年年份。注意&#xff1a;闰年的判别条件是该年年份能被4整除但不能被100整除、或者能被400整除。 输入格式: 输入在一行中给出21世纪的某个截止年份。 输出格式: 逐行输出满足条件的所有闰年年份&#xff0c;即每个年…

华为端到端战略管理体系(DSTE开发战略到执行)的运作日历图/逻辑图及DSTE三大子流程介绍

华为端到端战略管理体系&#xff08;DSTE开发战略到执行&#xff09;的运作日历图/逻辑图及DSTE三大子流程介绍 本文作者 | 谢宁&#xff0c;《华为战略管理法&#xff1a;DSTE实战体系》、《智慧研发管理》作者 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#…

【VASP】KPOINTS文件介绍

【VASP】KPOINTS文件介绍 一、KPOINTS 的两种结构第一种结构&#xff1a;&#xff08;非对称&#xff09;第二种结构&#xff1a;&#xff08;高对称&#xff09; 二、关于KPOINTS设置的一些经验三、KPOINTS的选取 前言 一、4个常用的输入文件INCAR、POSCAR、POTCAR、KPOINTS I…

MySQL [基础]] 学习笔记

MySQL 学习 文章目录 MySQL 学习1. 数据库三层结构2. 数据在数据库中的存储方式3. SQL 语句分类3.1 备份恢复数据库的表 4. Mysql 常用数据类型(列类型)4.1 数值型(整数)的基本使用4.2 数值型(bit)的使用4.3 数值型(小数)的基本使用4.4 字符串的基本使用(面试题)4.5 字符串使用…

基于springboot实现心灵治愈心理健康平台系统项目【项目源码+论文说明】

基于springboot实现心灵心理健康平台系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个心灵治愈交流平台 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论…

Linux友人帐之编译器gcc/g++的使用

一、程序的翻译过程 在C语言中&#xff0c;我们已经学过程序的编译和链接&#xff0c;在这里将复习一下我们之前所学的内容并引出后续gcc/g的内容。 1.1程序的翻译过程 预处理&#xff08;头文件展开&#xff0c;去注释&#xff0c;宏替换&#xff0c;条件编译&#xff09;编…

解决:由于找不到 VCRUNTIME140_.dll,无法继续执行代码。重新安装程序可能会解决此问题

最近我在安装一个软件时&#xff0c;遇到过这样的问题“由于找不到 VCRUNTIME140 1.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题”。 要解决这个问题&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 重新安装程序&#xff1a; 尝试重新安装使用…

Java NIO模型(提供代码示例)

目录 一、NIO特点介绍二、NIO代码实现2.1、客户端代码2.2、服务端代码 一、NIO特点介绍 NIO全称 java non-blocking IO。从JDK 1.4开始&#xff0c;java提供了一些列改进的输入/输出&#xff08;I/O&#xff09;的新特性&#xff0c;被称为NIO&#xff0c;是同步非阻塞的&…

蓝桥杯 常用STL (C++) 未完待续

动态数组 有些时候想开一个数组&#xff0c;但是却不知道应该开多大长度的数组合适&#xff0c;因为我们需要用到的数组可能会根据情况变动。 这时候我们就需要用到动态数组。所谓动态数组&#xff0c;也就是不定长数组&#xff0c;数组的长度是可以根据我们的需要动态改变的。…

Python数据类型转换

举例&#xff1a;使用Python实现超市的收银系统 name input(‘请输入您要购买商品名称&#xff1a;’) id input(‘请输入您要购买商品编号&#xff1a;’) price input(‘请输入您要购买的商品价格&#xff1a;’) print(f’您购买了{name}&#xff0c;商品编号为{id}&am…

《Deep Residual Learning for Image Recognition》阅读笔记

论文标题 《Deep Residual Learning for Image Recognition》 撑起CV界半边天的论文Residual &#xff1a;主要思想&#xff0c;残差。 作者 何恺明&#xff0c;超级大佬。微软亚研院属实是人才辈出的地方。 初读 摘要 提问题&#xff1a; 更深层次的神经网络更难训练。 …