华水967数据结构2024真题(回忆版)

一、 选择[10道) (20分).

1、数据结构中,从逻辑结构上可以把数据结构分为()

答案:线性结构和非线性结构

2、给了一个二叉树的中序遍历,求二叉树的后序遍历

解析:
要根据中序遍历的结果来推导后序遍历,需要知道二叉树的根节点。假设中序遍历的结果为inorder = [D, B, E, A, F, C, G],我们可以通过以下步骤来推导后序遍历:
步骤 1: 找到根节点
后序遍历的最后一个元素是根节点。假设我们知道根节点是 A。
步骤 2: 分割中序遍历
在中序遍历中找到根节点 A,将数组分成左子树和右子树:
左子树的中序遍历:[D, B, E]
右子树的中序遍历:[F, C, G]
步骤 3: 分割前序遍历
假设我们也有前序遍历的结果 preorder = [A, B, D, E, C, F, G],可以通过前序遍历来确定左右子树的根节点:
左子树的根节点是 B
右子树的根节点是 C
步骤 4: 递归处理左右子树
左子树
中序遍历:[D, B, E]
前序遍历:[B, D, E]
找到左子树的根节点 B,分割中序遍历:
左子树的中序遍历:[D]
右子树的中序遍历:[E]
递归处理:
左子树的根节点是 D,没有子节点
右子树的根节点是 E,没有子节点
右子树
中序遍历:[F, C, G]
前序遍历:[C, F, G]
找到右子树的根节点 C,分割中序遍历:
左子树的中序遍历:[F]
右子树的中序遍历:[G]
递归处理:
左子树的根节点是 F,没有子节点
右子树的根节点是 G,没有子节点
步骤 5: 合并结果
根据后序遍历的定义(左子树、右子树、根节点),我们可以从下往上合并结果:
左子树的后序遍历:[D, E, B]
右子树的后序遍历:[F, G, C]
整棵树的后序遍历:[D, E, B, F, G, C, A]

3、关于邻接表和邻接矩阵适用于稠密图/稀疏图的问题

解析:
邻接表适用于的情况
稀疏图:邻接表在存储稀疏图时更为节省空间。稀疏图的特点是边数远小于顶点数平方,因此使用邻接表可以避免为不存在的边分配空间。
应用场景:邻接表适用于边的数量远小于顶点数的平方的图,如社交网络、网络路由等。

邻接矩阵适用于的情况
稠密图:邻接矩阵在存储稠密图时更为高效。稠密图的特点是边数接近于顶点数平方,使用邻接矩阵可以直接通过矩阵访问判断两个顶点之间是否有边,时间复杂度为O(1)。
应用场景:邻接矩阵适用于边的数量接近于顶点数的平方的图,如完全图、密集网络等

4、给了一个二维数组A[M][N],计算另外一个数组的地址 例;设有A[6][5]数组,每数组占四个字节,告诉了起始地址,计算A[2][3]。

5、考查广义表head和tail方法使用 例;设广表A=(x,((a,b),c,d))。求Head (Head (Tail(A)))=?

解析:
Tail(A):
A 的尾部是从第二个元素开始的所有元素。
A = (x, ((a, b), c, d)),所以 Tail(A) = (((a, b), c, d))。
Head(Tail(A)):
Tail(A) = (((a, b), c, d)),其头部是第一个元素。
因此,Head(Tail(A)) = (c, d)。
Head(Head(Tail(A))):
Head(Tail(A)) = (c, d),其头部是第一个元素。
所以,Head(Head(Tail(A))) = ©。

6、中缀表达式和后缀表达式的转换

解析:
中缀表达式转后缀表达式
转换中缀表达式到后缀表达式的过程通常使用栈来实现。以下是转换的步骤:
1.初始化一个空栈和空的后缀表达式列表。
2.从左到右扫描中缀表达式的每个字符:
如果字符是操作数(数字或变量),直接添加到后缀表达式列表。
如果字符是左括号 (,压入栈。
如果字符是右括号 ),弹出栈中的元素直到遇到左括号 (,并将这些元素添加到后缀表达式列表。
如果字符是操作符(如 +, -, *, /),弹出栈中优先级大于或等于当前操作符的所有操作符,并将它们添加到后缀表达式列表,然后将当前操作符压入栈。
3.扫描完所有字符后,将栈中剩余的所有操作符弹出并添加到后缀表达式列表。

其他的记不清了, 24年选择题不难,都是往年真题迭择题中的基础题。

二、 简答题 (共3小问、20分)

1、 简述头指针、头结点、首元结点。

解析:

头指针

定义:头指针是指向链表第一个结点的指针。它并不存储任何数据,只是用来标识链表的起始位置。
作用:头指针是链表的必要元素,它允许我们访问链表中的第一个元素,从而开始遍历整个链表。

头结点

定义:头结点是链表中的一个特殊节点,它位于链表的最开始位置,但通常不存储实际的数据,而是作为链表的一个标识。
作用:头结点的主要作用是为链表提供一个统一的起点,使得链表的操作更加方便。它的存在使得在链表头部进行插入和删除操作时,不需要特别处理空链表的情况。

首元结点

定义:首元结点,也称为第一个元素结点,是链表中实际存储数据的第一个节点。
作用:首元结点是链表中的实际起始点,它后面跟随的是链表中的其他元素。通过首元结点,可以开始遍历链表并访问其数据。

2、 简述树(不是二叉树的三种存储结构,并说明其各自优缺点。

解析:
树(非二叉树)的三种存储结构分别是双亲表示法、孩子表示法和孩子兄弟表示法。以下是它们的优缺点:

双亲表示法

优点:可以很快得到每个结点的双亲结点。
缺点:求结点的孩子时需要遍历整个结构。

孩子表示法

优点:可以很快找到某个结点的所有子女(遍历该结点的孩子链表即可)。
缺点:寻找双亲操作需要遍历每个结点的孩子链表。

孩子兄弟表示法

优点:存储灵活,树转换为二叉树操作实现方便,易于查找结点的孩子等。
缺点:不易从当前结点查找其双亲结点(可以为每个结点增设一个parent域指向其父亲结点,但需要额外的空间开销)

3、详细写出堆排序的过程(题目给了一串数字)。

解析:
堆排序是一种基于二叉堆数据结构的比较排序算法,其基本思想是将待排序的序列构造成一个大顶堆(或小顶堆),然后将堆顶元素(最大值或最小值)与末尾元素交换,再调整剩余部分为新的堆,重复这个过程直到整个序列有序。以下是堆排序的详细过程:
堆排序的基本步骤
1.构建初始堆:将无序数组构造成一个大顶堆(或小顶堆)。这个过程通常从最后一个非叶子节点开始,向上遍历每个节点,如果节点的值小于其子节点的值,则将该节点与其子节点中值较小的一个交换,直到该节点满足大顶堆的条件。

2.堆排序:将堆顶元素(最大值或最小值)与堆的最后一个元素交换,此时末尾元素就成了最大值(或最小值)。然后将剩余元素重新构成一个堆,重复上述过程,直到堆中只剩下一个元素。
3.重复步骤2:每次从堆中取出最大(或最小)元素后,调整堆结构,使其重新满足大顶堆(或小顶堆)的性质,直到整个数组有序。

堆排序的时间复杂度和空间复杂度
时间复杂度:堆排序的时间复杂度为O(n log n),其中n是数组的大小。这是因为构建初始堆的时间复杂度为O(n),而每次堆调整的时间复杂度为O(log n),总共需要进行n-1次堆调整。
空间复杂度:堆排序的空间复杂度为O(1),因为它只需要一个额外的栈空间来存储原始数据,不需要额外的存储空间。

三、应用题、(共5题,记得4个)

1、利用栈模拟出算术表达式。(与2017年的综合题第一题类似)

解析:
算法步骤
1.初始化两个栈:一个用于存储操作数(operandStack),另一个用于存储运算符(operatorStack)。但在逆波兰表示法中,通常只需要一个操作数栈。

2.读取表达式:逐个读取表达式中的元素。

3.处理操作数:如果当前元素是数字,则将其压入操作数栈。

4.处理运算符:如果当前元素是运算符,则从操作数栈中弹出所需数量的操作数,执行运算,并将结果压回操作数栈。

5.重复步骤3和4,直到表达式处理完毕。

6.返回结果:表达式处理完毕后,操作数栈顶部的元素即为最终结果。

2、用两种方法求最小生成树,给出过程。

解析:

Prim算法

基本思想:从一个顶点开始,每次选择与当前生成树相连的权值最小的边,直到所有顶点都被包含。
步骤:
1.选择任意一个顶点作为起点,将其加入生成树集合。
2.在剩余未加入的顶点中找到与生成树集合中顶点相连的权值最小的边。
3.将这条边加入生成树集合,并将对应的顶点加入。
4.重复步骤2和3,直到所有顶点都被加入生成树集合。

Kruskal算法

基本思想:按照边的权值从小到大排序,依次选择边,如果这条边连接的两个顶点不在同一个连通分量中,则将它们合并,直到所有顶点都在同一个连通分量中。
步骤:
1.将所有边按权值从小到大排序。
2.初始化一个空集合,用来存放最小生成树的边。
3.依次取出权值最小的边,如果这条边的加入不会形成环,则将其加入最小生成树中。
4.重复步骤3,直到所有顶点都被包含在内。

3、 考查哈希函数,给了一组数据、哈希函数,让画哈希表和求平均查找长度。

4、考查关键路径问题

题中没直接给出图,题的大意是给出了顶点集V=S{a.b,c},边集
E=S{(a,b).(b.c)_},共三问。
第一问:画出这个图。
第二问:求顶点最早开始时间。
第三问:求顶点最晚开始时间。

24题给的不是边的权值,而是顶点完成所需的时间(之前没考)。

四、代码题(共四个,其中一个算是应用题)

1、代码填空题,共五个空。一个空两分,线性表的插入删除。

解析:

// 在指定位置插入元素
int insertElement(SeqList *list, int position, int element) {if (position < 0 || position > list->length || list->length >= MAXSIZE) {return -1; // 插入失败}for (int i = list->length; i > position; i--) {list->data[i] = list->data[i - 1];}list->data[position] = element;list->length++;return 0; // 插入成功
}// 删除指定位置的元素
int deleteElement(SeqList *list, int position) {if (position < 0 || position >= list->length) {return -1; // 删除失败}for (int i = position; i < list->length - 1; i++) {list->data[i] = list->data[i + 1];}list->length--;return 0; // 删除成功
}

2、给了图,让画出迪杰斯特拉的最短路径图。

3、写出查找一个数的代码,若找不出则把这个数插入数据(有序)。

解析:

// 二分查找函数,返回目标值的索引(若存在),否则返回-1
int binarySearch(int arr[], int size, int target) {int left = 0, right = size - 1;while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] == target) {return mid;} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1; // 未找到目标值
}// 在有序数组中插入元素,并保持数组有序
void insertSorted(int arr[], int *size, int target) {int index = binarySearch(arr, *size, target);if (index != -1) {// 若已存在目标值,则不进行插入(或根据需要处理)printf("元素 %d 已存在于数组中。\n", target);} else {// 在index位置插入目标值(需移动元素)for (int i = *size; i > index; i--) {arr[i] = arr[i - 1];}arr[index] = target;(*size)++; // 数组大小加1}
}

4、写出把一个二叉树中的结点存储到一个一维数组中的代码。

解析:

// 层序遍历函数,将节点值存储到数组中
void levelOrder(TreeNode* root, int* arr, int* index) {if (root == NULL) return; // 创建一个队列用于层序遍历TreeNode** queue = (TreeNode**)malloc(100 * sizeof(TreeNode*)); // 假设队列大小足够,实际应用中可能需要动态调整int front = 0, rear = 0;// 将根节点入队queue[rear++] = root;// 层序遍历while (front < rear) {TreeNode* currentNode = queue[front++];arr[(*index)++] = currentNode->val; // 将当前节点值存入数组// 左子节点入队if (currentNode->left != NULL) {queue[rear++] = currentNode->left;}// 右子节点入队if (currentNode->right != NULL) {queue[rear++] = currentNode->right;}}// 释放队列内存free(queue);
}

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

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

相关文章

Deepseek v3R1 学习笔记

o1 o1 模型在训练过程中混合了多种奖励函数的设计方法&#xff0c;并且尝试从结果监督转向过程监督&#xff0c;在中间过程进行打分 使用的搜索策略&#xff1a;基于树的搜索和基于顺序修改的搜索 R1 R1-Zero 是从基础模型开始&#xff0c;完全由强化学习驱动&#xff0c;不…

mybatisgenerator接入

1、引入plugin <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.mybatis.generator</groupId>&l…

NacosRce到docker逃逸实战

NacosRce到docker逃逸实战 1、Nacos Derby Rce打入内存马 这个漏洞的原理大家应该都知道&#xff0c; 2.3.2 < Nacos < 2.4.0版本默认derby接口未授权访问&#xff0c;攻击者可利用未授权访问执行SQL语句加载构造恶意的JAR包导致出现远程代码执行漏洞。 在日常的漏洞挖…

mini-lsm通关笔记Week2Day6

项目地址&#xff1a;https://github.com/skyzh/mini-lsm 个人实现地址&#xff1a;https://gitee.com/cnyuyang/mini-lsm Summary 在本章中&#xff0c;您将&#xff1a; 实现WAL日志文件的编解码 系统重启时使用WAL日志恢复memtable 要将测试用例复制到启动器代码中并运行…

【DeepSeek背后的技术】系列三:强化学习(Reinforcement Learning, RL)

目录 1 简介1.1 强化学习&#xff08;RL&#xff09;简介1.2 基于人类反馈的强化学习 (RLHF) 简介1.2.1 四个重要角色1.2.2 三个步骤 2 强化算法2.1 PPO&#xff08;Proximal Policy Optimization&#xff09;2.1.1 核心思想2.1.2 算法步骤2.1.3 优点2.1.4 缺点2.1.5 应用场景 …

LabVIEW的智能电源远程监控系统开发

在工业自动化与测试领域&#xff0c;电源设备的精准控制与远程管理是保障系统稳定运行的核心需求。传统电源管理依赖本地手动操作&#xff0c;存在响应滞后、参数调节效率低、无法实时监控等问题。通过集成工业物联网&#xff08;IIoT&#xff09;技术&#xff0c;实现电源设备…

SpringBoot开发(四)SpringBoot配置文件

1. SpringBoot配置文件 1.1. 配置端口号和路径 &#xff08;1&#xff09;在application.properties文件下配置端口号和路径。 server.port: 8081 server.servlet.context-path/demo&#xff08;2&#xff09;运行访问。 1.2. 自定义配置 1.2.1. 方式一 &#xff08;1&…

win32汇编环境,窗口程序中自定义工具栏的使用示例

;运行效果 ;win32汇编环境,窗口程序中自定义工具栏的使用示例 ;工具栏一般放在菜单下面&#xff0c;相当于一个个小的对话框&#xff0c;当然你放在其它地方也可以。 ;原理是&#xff0c;创建一张BMP位图&#xff0c;比如下例用一张168*24的图&#xff0c;平均分成7部分&#x…

机器学习专业毕设选题推荐合集 人工智能

目录 前言 毕设选题 开题指导建议 更多精选选题 选题帮助 最后 前言 大家好,这里是海浪学长毕设专题! 大四是整个大学期间最忙碌的时光&#xff0c;一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整理…

备考蓝桥杯嵌入式4:使用LCD显示我们捕捉的PWM波

上一篇博客我们提到了定时器产生PWM波&#xff0c;现在&#xff0c;我们尝试的想要捕获我们的PWM波&#xff0c;测量它的频率&#xff0c;我们应该怎么做呢&#xff1f;答案还是回到我们的定时器上。 我们知道&#xff0c;定时器是一个高级的秒表&#xff08;参考笔者的比喻&a…

ArrayList 扩容机制的源码剖析

在 Java 编程中&#xff0c;ArrayList是一个常用的集合类&#xff0c;它实现了List接口&#xff0c;底层基于数组实现。与普通定长数组不同&#xff0c;ArrayList能够根据元素的添加情况动态调整数组的大小&#xff0c;这就是其扩容机制。下面我们将深入剖析ArrayList扩容机制的…

The specified Gradle distribution ‘gradle-bin.zip‘ does not exist.

The specified Gradle distribution ‘https://services.gradle.org/distributions/gradle-bin.zip’ does not exist. distributionUrl不存在&#xff0c;关联不上&#xff0c;下载不了&#xff0c;那就匹配一个能下载的 distributionUrlhttps://services.gradle.org/distrib…

从零开始实现一个双向循环链表:C语言实战

文章目录 1链表的再次介绍2为什么选择双向循环链表&#xff1f;3代码实现&#xff1a;从初始化到销毁1. 定义链表节点2. 初始化链表3. 插入和删除节点4. 链表的其他操作5. 打印链表和判断链表是否为空6. 销毁链表 4测试代码5链表种类介绍6链表与顺序表的区别7存储金字塔L0: 寄存…

Cesium点集中获取点的id,使用viewer.value.entities.getById报错的解决方法

错误代码&#xff1a; viewer.value.entities.getById(pickedObject.id) 报错&#xff1a; 可以正常获取movement.position但是一直出现如下报错&#xff0c;无法获得航点的id&#xff0c;通过断点定位为 viewer.value.entities.getById(pickedObject.id)导致的报错 解决方…

ARM Linux Qt使用JSON-RPC实现前后台分离

文章目录 1、前言2、解决方案2.1、JSON-RPC2.2、Qt中应用JSON-RPC的框架图2.3、优点2.4、JSON-RPC 1.0 协议规范 3、程序示例3.1、Linux C&#xff08;只例举RPC Server相关程序&#xff09;3.2、Qt程序&#xff08;只例举RPC Client相关程序&#xff09; 4、编译程序4.1、交叉…

教程 | i.MX RT1180 ECAT_digital_io DEMO 搭建(一)

本文介绍 i.MX RT1180 EtherCAT digital io DEMO 搭建&#xff0c;Master 使用 TwinCAT &#xff0c;由于步骤较多&#xff0c;分为上下两篇&#xff0c;本文为第一篇&#xff0c;主要介绍使用 TwinCAT 控制前的一些准备。 原厂 SDK 提供了 evkmimxrt1180_ecat_examples_digit…

ubuntu22.40安装及配置静态ip解决重启后配置失效

遇到这种错误&#xff0c;断网安装即可&#xff01; 在Ubuntu中配置静态IP地址的步骤如下。根据你使用的Ubuntu版本&#xff08;如 Netplan 或传统的 ifupdown&#xff09;&#xff0c;配置方法有所不同。以下是基于 Netplan 的配置方法&#xff08;适用于Ubuntu 17.10及更高版…

【产品经理学习案例——AI翻译棒出海业务】

前言&#xff1a; 本文主要讲述了硬件产品在出海过程中&#xff0c;翻译质量、翻译速度和本地化落地策略是硬件产品规划需要考虑的核心因素。针对不同国家&#xff0c;需要优化翻译质量和算法&#xff0c;关注市场需求和文化差异&#xff0c;以便更好地满足当地用户的需求。同…

CH340G上传程序到ESP8266-01(S)模块

文章目录 概要ESP8266模块外形尺寸模块原理图模块引脚功能 CH340G模块外形及其引脚模块引脚功能USB TO TTL引脚 程序上传接线Arduino IDE 安装ESP8266开发板Arduino IDE 开发板上传失败上传成功 正常工作 概要 使用USB TO TTL&#xff08;CH340G&#xff09;将Arduino将程序上传…

AI推理性能之王-Groq公司开发的LPU芯片

Groq公司开发的LPU&#xff08;Language Processing Unit&#xff0c;语言处理单元&#xff09;芯片是一种专为加速大规模语言模型&#xff08;LLM&#xff09;和其他自然语言处理任务而设计的新型AI处理器。以下是对其技术特点、性能优势及市场影响的深度介绍&#xff1a; 技…