王道数据结构课后代码题p150 第13——17 (c语言代码实现)

目录

13.p 和 q 分别为指向该二叉树中任意两个结点的指针,试编写算法 ANCESTOR(ROOT,P,q,r),找到P和q的最近公共祖先结点 r

 14.假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树 b的宽度(即具有结点数最多的那一层的结点个数) 

 15.设有一棵满二叉树(所有结点值均不同),已知其先序序列为 pre,设计一个算法求其后序序列post。

 16.设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为 head.二叉树按二叉链表方式存储,链接时用叶结点的右指针域来存放单链表指针。

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


13.p 和 q 分别为指向该二叉树中任意两个结点的指针,试编写算法 ANCESTOR(ROOT,P,q,r),找到P和q的最近公共祖先结点 r

 后序遍历最后访问根结点,即在递归算法中,根是压在栈底的。本题要找 p 和g 的最近公共祖先结点了,不失一般性,设p在 的左边。算法思想:采用后序非递归算法,栈中存放二又树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。后序遍历必然先遍历到结点p,栈中元素均为 p 的祖先。先将栈复制到另一辅助栈中。继续遍历到结点  时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配(即相等)的元素就是结点p和的最近公共祖先。

本题代码如下

// 查找二叉树中两个节点的最近公共祖先的函数,输入为一个指向tree的指针,以及两个指向treenode的指针p和q  
tree find(tree* t, treenode* p, treenode* q)
{// 定义两个stack数组s1和s2,以及两个栈顶指针top1和top2,用于深度优先搜索  stack s1[10], s2[10];int top1 = -1, top2 = -1;treenode* tt = *t;// 当tt不为NULL或者栈s1不为空时,循环执行以下操作  while (tt != NULL || top1 != -1){// 当tt不为NULL时,循环执行以下操作,将tt及其所有左子节点压入栈s1中,并标记tag为0  while (tt != NULL){s1[++top1].t = tt;s1[top1].tag = 0;tt = tt->lchild;}// 当栈s1不为空且栈顶元素的tag为1时,循环执行以下操作,检查栈顶元素是否为p或q,如果是,则将其压入栈s2中  while (top1 != -1 && s1[top1].tag == 1){if (s1[top1].t == p){for (int i = 0; i <= top1; i++){s2[i] = s1[i];}top2 = top1;}if (s1[top1].t == q){// 从栈s1和栈s2的顶部开始,逐一对比两个栈中的元素,如果找到相同的元素,则返回该元素的指针,这就是p和q的最近公共祖先  for (int i = top1; i >= 0; i--){for (int j = top2; j >= 0; j--){if (s2[j].t == s1[i].t)return s1[i].t;}}}top1--;}// 如果栈s1不为空,则将栈顶元素的tag设为1,并将tt设为栈顶元素的右子节点,开始遍历右子树  if (top1 != -1){s1[top1].tag = 1;tt = s1[top1].t->rchild;}}// 如果遍历完整棵树都没有找到公共祖先,则返回NULL  return NULL;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
} treenode, * tree;
typedef struct
{treenode* t;int tag;
} stack;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
// 查找二叉树中两个节点的最近公共祖先的函数,输入为一个指向tree的指针,以及两个指向treenode的指针p和q  
tree find(tree* t, treenode* p, treenode* q)
{// 定义两个stack数组s1和s2,以及两个栈顶指针top1和top2,用于深度优先搜索  stack s1[10], s2[10];int top1 = -1, top2 = -1;treenode* tt = *t;// 当tt不为NULL或者栈s1不为空时,循环执行以下操作  while (tt != NULL || top1 != -1){// 当tt不为NULL时,循环执行以下操作,将tt及其所有左子节点压入栈s1中,并标记tag为0  while (tt != NULL){s1[++top1].t = tt;s1[top1].tag = 0;tt = tt->lchild;}// 当栈s1不为空且栈顶元素的tag为1时,循环执行以下操作,检查栈顶元素是否为p或q,如果是,则将其压入栈s2中  while (top1 != -1 && s1[top1].tag == 1){if (s1[top1].t == p){for (int i = 0; i <= top1; i++){s2[i] = s1[i];}top2 = top1;}if (s1[top1].t == q){// 从栈s1和栈s2的顶部开始,逐一对比两个栈中的元素,如果找到相同的元素,则返回该元素的指针,这就是p和q的最近公共祖先  for (int i = top1; i >= 0; i--){for (int j = top2; j >= 0; j--){if (s2[j].t == s1[i].t)return s1[i].t;}}}top1--;}// 如果栈s1不为空,则将栈顶元素的tag设为1,并将tt设为栈顶元素的右子节点,开始遍历右子树  if (top1 != -1){s1[top1].tag = 1;tt = s1[top1].t->rchild;}}// 如果遍历完整棵树都没有找到公共祖先,则返回NULL  return NULL;
}
int main()
{tree t;buildtree(&t);treenode* p = t->rchild->lchild, * q = t->rchild->rchild;treenode* result = find(&t, p, q);if (result)printf("%c与%c的最近公共祖先为:%c",p->data,q->data,result->data);elseprintf("没找到公共祖先");return 0;
}

用ABD##E##CF##G##测试

/*                       A

            B                        C

D                   E      F                 G     */

 14.假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树 b的宽度(即具有结点数最多的那一层的结点个数) 

  采用层次遍历的方法求出所有结点的层次,并将所有结点和对应的层次放在一个队列中。然后通过扫描队列求出各层的结点总数,最大的层结点总数即为二叉树的宽度。

/*                       A

            B                        C

D                   E      F                 G     */

本题代码如下

int width(tree* t)
{quene q;tree p;int k;q.f = q.r = -1;//队列为空q.r++;q.data[q.r] = *t;//根结点进队q.level[q.r] = 1;//根结点层次为1while (q.f < q.r){q.f++;//出队p = q.data[q.f];//出队结点k = q.level[q.f];//出队结点的层次if (p->lchild != NULL)//左孩子进队{q.r++;q.data[q.r] = p->lchild;q.level[q.r] = k + 1;}if (p->rchild != NULL)//右孩子进队{q.r++;q.data[q.r] = p->rchild;q.level[q.r] = k + 1;}}int max = 0;//保留同一层最多的结点个数int i = 0;//i扫描队中的所有元素k = 1;//k表示从第一层开始查找int n;//n统计第k层中的结点个数while (i <=q.r){n = 0;while (i <=q.r && q.level[i] == k)//记录同一层有多少元素{n++;i++;}k = q.level[i];//将k等于下一层的层数if (n > max)//保留最大的nmax = n;}return max;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
}treenode,*tree;
typedef struct
{tree data[10];int level[10];int f, r;
}quene;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch =='#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
int width(tree* t)
{quene q;tree p;int k;q.f = q.r = -1;//队列为空q.r++;q.data[q.r] = *t;//根结点进队q.level[q.r] = 1;//根结点层次为1while (q.f < q.r){q.f++;//出队p = q.data[q.f];//出队结点k = q.level[q.f];//出队结点的层次if (p->lchild != NULL)//左孩子进队{q.r++;q.data[q.r] = p->lchild;q.level[q.r] = k + 1;}if (p->rchild != NULL)//右孩子进队{q.r++;q.data[q.r] = p->rchild;q.level[q.r] = k + 1;}}int max = 0;//保留同一层最多的结点个数int i = 0;//i扫描队中的所有元素k = 1;//k表示从第一层开始查找int n;//n统计第k层中的结点个数while (i <=q.r){n = 0;while (i <=q.r && q.level[i] == k)//记录同一层有多少元素{n++;i++;}k = q.level[i];//将k等于下一层的层数if (n > max)//保留最大的nmax = n;}return max;
}
int main()
{tree t;buildtree(&t);int widthnum = width(&t);printf("二叉树的宽度为:%d", widthnum);return 0;
}

用ABD##E##CF##G##测试

/*                       A

            B                        C

D                   E      F                 G     */

 15.设有一棵满二叉树(所有结点值均不同),已知其先序序列为 pre,设计一个算法求其后序序列post。

  对一般二叉树,仅根据先序或后序序列,不能确定另一个遍历序列。但对满二叉树,任意一个结点的左、右子树均含有相等的结点数,同时,先序序列的第一个结点作为后序序列的最后个结点。

本题代码如下

void pretopost(char *pre,int l1,int h1,char post[],int l2,int h2)
{int half = 0;if (h1 >= l1){post[h2] = pre[l1];//后序最右端等于先序最左端half = (h1 - l1) / 2;pretopost(pre, l1 + 1, l1 + half, post, l2, l2 + half - 1);//转换左子树pretopost(pre, l1 + half + 1, h1, post, l2 + half, h2 - 1);//转换右子树}
}

完整测试代码

#include<stdio.h>
void pretopost(char *pre,int l1,int h1,char post[],int l2,int h2)
{int half = 0;if (h1 >= l1){post[h2] = pre[l1];//后序最右端等于先序最左端half = (h1 - l1) / 2;pretopost(pre, l1 + 1, l1 + half, post, l2, l2 + half - 1);//转换左子树pretopost(pre, l1 + half + 1, h1, post, l2 + half, h2 - 1);//转换右子树}
}
int main()
{char *pre = "ABDECFG";char post[10];pretopost(pre, 0, 6, post, 0, 6);printf("后序序列为:");for (int i = 0; i <= 6; i++)printf("%c", post[i]);return 0;
}

 16.设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为 head.二叉树按二叉链表方式存储,链接时用叶结点的右指针域来存放单链表指针。

 通常我们所用的先序、中序和后序遍历对于叶结点的访问顺序都是从左到右,这里我们选择中序递归遍历。

设置前驱结点指针 pre,初始为空。第一个叶结点由指针 head 指向,遍历到叶结点时,就将它前驱的 rchild 指针指向它,最后一个叶结点的 rchild 为空。

本题代码如下

tree head =NULL, pre = NULL;
tree inorder(tree* t)
{if (*t){inorder(&(*t)->lchild);//中序遍历左子树if ((*t)->lchild == NULL && (*t)->rchild == NULL)//处理叶结点if(pre==NULL){head = *t;pre = *t;//处理第一个叶结点}else{pre->lchild = *t;pre = *t;//将叶结点链入链表}inorder(&(*t)->rchild);//中序遍历右子树pre->rchild = NULL;//设置链表尾}return head;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
}treenode,*tree;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch =='#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
tree head =NULL, pre = NULL;
tree inorder(tree* t)
{if (*t){inorder(&(*t)->lchild);//中序遍历左子树if ((*t)->lchild == NULL && (*t)->rchild == NULL)//处理叶结点if(pre==NULL){head = *t;pre = *t;//处理第一个叶结点}else{pre->lchild = *t;pre = *t;//将叶结点链入链表}inorder(&(*t)->rchild);//中序遍历右子树pre->rchild = NULL;//设置链表尾}return head;
}
int main()
{tree t;buildtree(&t);head=inorder(&t);while (head){printf("%c", head->data);head = head->lchild;}return 0;
}

用ABD##E##CF##G##测试

/*                       A

            B                        C

D                   E      F                 G     */

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

 若T1和T2都是空树,则相似;若有一个为空另一个不空,则必然不相似:否则递归地比较它们的左、右子树是否相似。

本题代码如下

int similar(tree* t1, tree* t2)
{int lefts, rights;if (*t1 == NULL && *t2 == NULL)//两树皆空return 1;else if (*t1 == NULL || *t2 == NULL)//只有一树为空return 0;else//递归判断{lefts = similar(&(*t1)->lchild, &(*t2)->lchild);rights = similar(&(*t1)->rchild, &(*t2)->rchild);return (lefts && rights);}
}

完整测试代码为

#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
} treenode, * tree;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
int similar(tree* t1, tree* t2)
{int lefts, rights;if (*t1 == NULL && *t2 == NULL)//两树皆空return 1;else if (*t1 == NULL || *t2 == NULL)//只有一树为空return 0;else//递归判断{lefts = similar(&(*t1)->lchild, &(*t2)->lchild);rights = similar(&(*t1)->rchild, &(*t2)->rchild);return (lefts && rights);}
}
int main()
{tree t1, t2;buildtree(&t1);getchar();buildtree(&t2);int T = similar(&t1, &t2);if (T == 1)printf("相似");elseprintf("不相似");return 0;
}

用下面的两棵树测试

/*

第一棵树

    A
B            
AB###

第二棵树
    C
        D
C#D##

换另外一种测试

/*

第一棵树

    A       
A##

第二棵树
    C
C##

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

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

相关文章

SD-WAN解决企业国际互联组网需求

随着云计算、移动应用和企业全球化的浪潮&#xff0c;实时应用在不同地点之间的传输需求不断增加&#xff0c;涵盖异地办公、视频会议、远程桌面、支付交易系统以及远程医疗等。这些应用的顺畅传输对于企业至关重要&#xff0c;而SD-WAN&#xff08;软件定义广域网&#xff09;…

Spring MVC详解、静态资源访问、拦截器

1. Spring MVC概述 1.1 Spring MVC是什么 SpringMVC是Spring的一个模块&#xff0c;是一个基于MVC设计模式的web框架。 1.2 Spring MVC执行流程。 1.3 组件分析 前端控制器&#xff08;默认配置&#xff09;Dispatcher Servlet 作用&#xff1a;只负责分发请求。可以很好的对…

这样的软件测试面试题,谁面试遇到谁淘汰!!!

88 11.6 自动化测试用例的来源 手工编写测试用例 把原来手工的测试用例&#xff0c;当成自动化测试用例 11.7 自动化测试的优点与缺点 优点: 1、对程序的回归测试更方便 2、可以运行更多更繁琐的测试 3、提高测试效率和准确性&#xff0c;节约时间成本 4、可以执行一些手工测试…

手把手教你玩转ESP8266(原理+驱动)

在嵌入式开发中&#xff0c;无线通信的方式有很多&#xff0c;其中 WIFI 是绕不开的话题。说到 WIFI 通信&#xff0c;就不得不提 ESP8266了。 ESP8266 是一款高性能的 WIFI 串口模块&#xff0c;实现透明传输。只要有一定的串口知识&#xff0c;不需要知道 WIFI 原理就可以上…

作为一个产品经理带你了解Axure的安装和基本使用

1.Axure的简介 Axure是一种强大的原型设计工具&#xff0c;它允许用户创建交互式的、高保真度的原型&#xff0c;以及进行用户体验设计和界面设计。Axure可以帮助设计师和产品经理快速创建和共享原型&#xff0c;以便团队成员之间进行沟通和反馈。Axure提供了丰富的交互组件和功…

Spring--10--Spring Bean的生命周期

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.Spring Bean1.1 什么是 Bean简而言之&#xff0c;bean 是由 Spring IoC 容器实例化、组装和管理的对象。 1.2 Spring框架管理Bean对象的优势 2.Bean的生命周期实例…

西工大网络空间安全学院计算机系统基础实验二(phase_2下——漫漫深夜过后的黎明!!!)

内存地址内存地址中的数注释指向这块内存的寄存器0xffffd0e8函数phase_2的栈帧0xffffd0e40xffffd0f4函数phase_2的栈帧0xffffd0e00x5655b7b0函数phase_2的栈帧0xffffd0dc0x565566ca函数read_six_numbers的返回地址&#xff0c;函数phase_2的栈帧0xffffd0d80x5655af64旧%ebx的值…

SpringIOC之ConditionEvaluator

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

一文读懂MySQL基础知识文集(8)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

单目相机测距(3米范围内)二维码实现方案(python代码 仅仅依赖opencv)

总体思路:先通过opencv 识别二维码的的四个像素角位置,然后把二维码的物理位置设置为 cv::Point3f(-HALF_LENGTH, -HALF_LENGTH, 0), //tl cv::Point3f(HALF_LENGTH, -HALF_LENGTH, 0), //tr cv::Point3f(HALF_LENGTH, HALF_LENGTH, 0), //br cv::P…

软件运行原理 - 内存模型 - 栈内存

说明 C/C软件运行时&#xff0c;内存根据使用方式的不同分为堆内存和栈内存&#xff0c;栈内存使用有以下特征&#xff1a; 栈内存使用&#xff08;申请、释放&#xff09;由系统自动分配和释放&#xff0c;程序员不用做任何操作。栈内存重复使用&#xff0c;进入函数时数据入…

什么是特征图?

在卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;特征图是在传递给卷积层的图像上发生卷积操作后卷积层的输出。 特征图是如何形成的&#xff1f; 在上面的插图中&#xff0c;我们可以看到特征图是如何从提供的输入图像中形成的。 要发送到卷积层的图像是一个包含像…

微服务网关组件Gateway实战

1. 需求背景 在微服务架构中&#xff0c;通常一个系统会被拆分为多个微服务&#xff0c;面对这么多微服务客户端应该如何去调用呢&#xff1f;如果根据每个微服务的地址发起调用&#xff0c;存在如下问题&#xff1a; 客户端多次请求不同的微服务&#xff0c;会增加客户端代码…

聚首引领行业风潮!聚首品牌联动资源价值平台发布会正式启航

2023年12月10日&#xff0c;由杭州建筑装饰学会、浙江聚首联优材料科技有限公司主办&#xff0c;天尚设计集团、公和设计集团、铭扬工程设计集团、地标设计集团、上宸工程设计集团、华坤建筑设计院、广厦建筑设计研究院、上海传承博华建筑规划设计院、航冠工程设计院、浙江鸿能…

设计模式——建造者模式(创建型)

引言 生成器模式是一种创建型设计模式&#xff0c; 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 问题 假设有这样一个复杂对象&#xff0c; 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码…

Python3开发环境的搭建

1&#xff0c;电脑操作系统的确认 我的是win10、64位的&#xff0c;你们的操作系统可自寻得。 2&#xff0c;Python安装包的下载 &#xff08;1&#xff09;浏览器种输入网址&#xff1a;https://www.python.org 选择对应的系统&#xff08;我的是win10/64位) &#xf…

设计模式(二)-创建者模式(5)-建造者模式

一、为何需要建造者模式&#xff08;Builder&#xff09;? 在软件系统中&#xff0c;会存在一个复杂的对象&#xff0c;复杂在于该对象包含了很多不同的功能模块。该对象里的各个部分都是按照一定的算法组合起来的。 为了要使得复杂对象里的各个部分的独立性&#xff0c;以及…

腾讯物联网平台之规则引擎

1.腾讯物联网平台简介 腾讯云物联网开发平台&#xff08;IoT Explorer&#xff09;为客户提供便捷的物联网开发工具与服务&#xff0c;助力客户更高效的完成设备接入&#xff0c;并为客户提供物联网应用开发及场景服务能力&#xff0c;帮助客户高效、低成本构建物联网应用。  …

SpringBoot集成系列--RabbitMQ

文章目录 一、代码1、添加依赖2、配置RabbitMQ连接3、RabbitMQ配置4、创建生产者5、创建消费者6、测试 二、遇到的问题1、Channel shutdown2、收不到信息3、安装RabbitMQ&#xff0c;无法访问控制台访问 一、代码 1、添加依赖 在pom.xml文件中添加RabbitMQ的相关依赖 <de…

Leetcode—228.汇总区间【简单】

2023每日刷题&#xff08;五十六&#xff09; Leetcode—228.汇总区间 解题思路 我们可以用双指针left 和 right找出每个区间的左右端点。 遍历数组&#xff0c;当right 1< n 且 nums[right1]nums[right]1 时&#xff0c;指针right向右移动&#xff0c;否则区间 [left, …