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

news2025/2/8 21:55:29

一、 选择[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.coloradmin.cn/o/2294956.html

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

相关文章

javaEE初阶————多线程初阶(3)

大家新年快乐呀&#xff0c;今天是第三期啦&#xff0c;大家前几期的内容掌握的怎么样啦&#xff1f; 1&#xff0c;线程死锁 1.1 构成死锁的场景 a&#xff09;一个线程一把锁 这个在java中是不会发生的&#xff0c;因为我们之前讲的可重入机制&#xff0c;在其他语言中可…

【Flink快速入门-1.Flink 简介与环境配置】

Flink 简介与环境配置 实验介绍 在学习一门新的技术之前&#xff0c;我们首先要了解它的历史渊源&#xff0c;也就是说它为什么会出现&#xff0c;它能够解决什么业务痛点。所以本节我们的学习目的是了解 Flink 的背景&#xff0c;并运行第一个 Flink 程序&#xff0c;对它有…

WPF基础 | 初探 WPF:理解其核心架构与开发环境搭建

WPF基础 | 初探 WPF&#xff1a;理解其核心架构与开发环境搭建 一、前言二、WPF 核心架构2.1 核心组件2.2 布局系统2.3 数据绑定机制2.4 事件处理机制 三、WPF 开发环境搭建3.1 安装 Visual Studio3.2 创建第一个 WPF 应用程序 结束语优质源码分享 WPF基础 | 初探 WPF&#xff…

JVM 四虚拟机栈

虚拟机栈出现的背景 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的。优点是跨平台&#xff0c;指令集小&#xff0c;编译器容易实现&#xff0c;缺点是性能下降&#xff0c;实现同样的功能需要更多…

深入理解小波变换:信号处理的强大工具

引言 在科学与工程领域&#xff0c;信号处理一直是关键环节&#xff0c;傅里叶变换与小波变换作为重要的分析工具&#xff0c;在其中发挥着重要作用。本文将深入探讨小波变换&#xff0c;阐述其原理、优势以及与傅里叶变换的对比&#xff0c;并通过具体案例展示其应用价值。 一…

【大数据技术】搭建完全分布式高可用大数据集群(Kafka)

搭建完全分布式高可用大数据集群(Kafka) kafka_2.13-3.9.0.tgz注:请在阅读本篇文章前,将以上资源下载下来。 写在前面 本文主要介绍搭建完全分布式高可用集群 Kafka 的详细步骤。 注意: 统一约定将软件安装包存放于虚拟机的/software目录下,软件安装至/opt目录下。 安…

关于ESP-IDF 5.4 中添加第三方组件esp32-camera找不到文件,编译错误解决办法(花了一天时间解决)

最近需要使用ESP32-S3-CAM 的OV2640摄像头采集图像&#xff0c;为了加速开发进度&#xff0c;于是选择了esp32-camera组件&#xff0c;该组件不是官方组件&#xff0c;需要自己git clone。但在为项目添加esp32-camera组件时&#xff0c;一直编译错误&#xff0c;找不到头文件&a…

Android LifecycleOwner 闪退,java 继承、多态特性!

1. 闪退 同意隐私政策后&#xff0c;启动进入游戏 Activity 闪退 getLifecycle NullPointerException 空指针异常 FATAL EXCEPTION: main Process: com.primer.aa.gg, PID: 15722 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.primer.aa.…

[LeetCode]day16 242.有效的字母异位词

242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的 字母异位词 示例 1: 输入: s "anagram", t "nagaram" 输出: true示例 2: 输入: s "rat"…

基于SpringBoot养老院平台系统功能实现五

一、前言介绍&#xff1a; 1.1 项目摘要 随着全球人口老龄化的不断加剧&#xff0c;养老服务需求日益增长。特别是在中国&#xff0c;随着经济的快速发展和人民生活水平的提高&#xff0c;老年人口数量不断增加&#xff0c;对养老服务的质量和效率提出了更高的要求。传统的养…

【3分钟极速部署】在本地快速部署deepseek

第一步&#xff0c;找到网站&#xff0c;下载&#xff1a; 首先找到Ollama &#xff0c; 根据自己的电脑下载对应的版本 。 我个人用的是Windows 我就先尝试用Windows版本了 &#xff0c;文件不是很大&#xff0c;下载也比较的快 第二部就是安装了 &#xff1a; 安装完成后提示…

Linux ftrace 内核跟踪入门

文章目录 ftrace介绍开启ftraceftrace使用ftrace跟踪指定内核函数ftrace跟踪指定pid ftrace原理ftrace与stracetrace-cmd 工具KernelShark参考 ftrace介绍 Ftrace is an internal tracer designed to help out developers and designers of systems to find what is going on i…

[Day 16]螺旋遍历二维数组

今天我们看一下力扣上的这个题目&#xff1a;146.螺旋遍历二维数组 题目描述&#xff1a; 给定一个二维数组 array&#xff0c;请返回「螺旋遍历」该数组的结果。 螺旋遍历&#xff1a;从左上角开始&#xff0c;按照 向右、向下、向左、向上 的顺序 依次 提取元素&#xff0c…

【教程】docker升级镜像

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 自动升级 手动升级 无论哪种方式&#xff0c;最重要的是一定要通过-v参数做数据的持久化&#xff01; 自动升级 使用watchtower&#xff0c;可…

使用jmeter进行压力测试

使用jmeter进行压力测试 jmeter安装 官网安装包下载&#xff0c;选择二进制文件&#xff0c;解压。 tar -xzvf apache-jmeter-x.tgz依赖jdk安装。 yum install java-1.8.0-openjdk环境变量配置&#xff0c;修改/etc/profile文件&#xff0c;添加以下内容。 export JMETER/…

链表和 list

一、单链表的模拟实现 1.实现方式 链表的实现方式分为动态实现和静态实现两种。 动态实现是通过 new 申请结点&#xff0c;然后通过 delete 释放结点的形式构造链表。这种实现方式最能体 现链表的特性&#xff1b; 静态实现是利用两个数组配合来模拟链表。一个表示数据域&am…

【AI大模型】Ubuntu18.04安装deepseek-r1模型+服务器部署+内网访问

以下内容主要参考博文&#xff1a;DeepSeek火爆全网&#xff0c;官网宕机&#xff1f;本地部署一个随便玩「LLM探索」 - 程序设计实验室 - 博客园 安装 ollama Download Ollama on Linux curl -fsSL https://ollama.com/install.sh | sh 配置 ollama 监听地址 ollama 安装后…

cmd执行mysql命令

安装mysql之后如果想使用cmd执行mysql命令&#xff0c;需要怎么操作呢&#xff0c;下面一起看一下。 安装mysql之后&#xff0c;如果直接去cmd窗口执行MySQL命令&#xff0c;窗口可能会提示mysql不是可执行命令。 需要配置系统的环境变量&#xff0c;将mysql的安装路径配置系…

网络安全威胁框架与入侵分析模型概述

引言 “网络安全攻防的本质是人与人之间的对抗&#xff0c;每一次入侵背后都有一个实体&#xff08;个人或组织&#xff09;”。这一经典观点概括了网络攻防的深层本质。无论是APT&#xff08;高级持续性威胁&#xff09;攻击、零日漏洞利用&#xff0c;还是简单的钓鱼攻击&am…

详细教程 | 如何使用DolphinScheduler调度Flink实时任务

Apache DolphinScheduler 非常适用于实时数据处理场景&#xff0c;尤其是与 Apache Flink 的集成。DolphinScheduler 提供了丰富的功能&#xff0c;包括任务依赖管理、动态调度、实时监控和日志管理&#xff0c;能够有效简化 Flink 实时任务的管理和部署。通过 DolphinSchedule…