BUAA数据结构期中考试2023

2023-11-02 00:40

本文主要是介绍BUAA数据结构期中考试2023,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • BUAA数据结构期中考试2023
    • 1. 密码对应表
      • 题目
        • 问题描述
        • 输入形式
        • 输出形式
        • 样例输入
        • 样例输出
        • 样例说明
        • 评分标准
      • 问题分析
      • 完整代码
    • 2. 基于前移法的链表查找
      • 题目
        • 问题描述
        • 输入形式
        • 输出形式
        • 样例输入
        • 样例输出
        • 样例说明
        • 评分标准
      • 问题分析
      • 具体实现过程
      • 完整代码

BUAA数据结构期中考试2023

1. 密码对应表

题目

问题描述

有一种加密方法为:其使用一个字符串(可以含重复字母,字符个数不超过50)作为密钥。例如:若密钥字符串为Fea25Ther,则需 要先将大写字母转换成小写字母,并去掉密钥单词中的非字母及重复字母得到单词串feathr,然后将其反序,最后将字母表中的其 它字母以反序追加到后面

rhtaefzyxwvusqponmlkjigdcb

加密字母的对应关系如下:

abcdefghijklmnopqrstuvwxyz
rhtaefzyxwvusqponmlkjigdcb

编写程序根据输入的密钥,生成相应的密码对应表串。

输入形式

从标准输入读入密钥字符串(字符个数不超过50,其中可包含空白符或其它非字母字符),末尾有换行符(不属于密钥字符串)

输出形式

先向控制台输出原字母表,然后在下一行输出生成的对应密码表。

样例输入

Fea25Ther

样例输出

abcdefghijklmnopqrstuvwxyz

rhtaefzyxwvusqponmlkjigdcb

样例说明

输入的密钥字符串为Fea25Ther,先将大写字母转换成小写字母,并去掉密钥单词中的非字母及重复字母得到单词串feathr,然后将 其反序,最后将字母表中的其它字母以反序追加到后面,便得到密码表。

评分标准

该题要求生成密码对应表,提交程序名为:key.c。

问题分析

本题几乎是第二次作业第三题的原题,甚至比原题还要简单——没有涉及文件的输入输出操作。此处相比原题只有了两处变动:

  1. 输入的可能不是字母,所以我们只需要在读的时候针对字符串的每一位都判断一下是否是字母再操作。
  2. 可能有大写字母,我们要把它转化成小写字母。
  3. 先要对处理完的字符串逆序

由于基本是原题,此处不再给出具体分析过程,所有思路都蕴含在注释中。

完整代码

#include <stdio.h>
#include <string.h>
# include <ctype.h>char secret_key [27];  // 加密对应表int main()
{char org_word[55] = {0};  // 最开始读取的秘钥gets(org_word);int already_used[26] = {0};  // 记录哪些积木已经被用过了(字母1-26编号)int count = 0;for(int i = 0; org_word[i]; i++){if (isalpha(org_word[i])){  // 判断当前位置是否是字母org_word[i] = tolower(org_word[i]);  // 是字母,转化成小写形式if(!already_used[org_word[i] - 'a']){  // 没被用过already_used[org_word[i] - 'a'] = 1;secret_key[count++] = org_word[i];           }}       }   //接下来要对secret_key逆序,可以有很多种方法,考试时可以就用最笨的方法——开一个tmp数组存储其逆序后的结果,然后copy回去char tmp[100]= {0};for (int i=0; i < count; i++){tmp[count-1-i] = secret_key[i];}// 现在tmp已经是secret_key逆序后的数组了strcpy(secret_key, tmp);for(int i = 25; i >= 0; i--){if(!already_used[i]){           secret_key [count++] = 'a' + i;}}// 输出for(int i = 0; i < 26; i++){printf("%c", 'a' + i);}printf("\n");for (int i = 0; i < 26; i++)printf("%c", secret_key[i]);return 0;
}

2. 基于前移法的链表查找

题目

问题描述

链表结构存在一个严重不足,就是需要顺序查找才能找到所需要的元素,查找性能低,下面为一个改进链表查找效率的方法。 链表构造规则如下:

  1. 初始时链表为空;
  2. 若元素不在链表中,将其加到链表尾
  3. 若元素在链表中,则将该元素移到链表头(若元素已在链表头则不移动)。

编写程序,对输入的一组整数,依次在上述规则构建的链表中查找每个整数。 假如依次输入了15个整数,分别为:-200 120 85 97 2900 85 696 -120 85 120 85 120 85 97 120,前五个数据输入后,构建的链表如 下所示:

在这里插入图片描述

结点中前面的数据表示输入的整数,后面的数据是该整数的出现次数。输入第六个数据后,构建的链表如下所示:

在这里插入图片描述

所有整数输入完毕后,构建的链表如下所示:

在这里插入图片描述

输入形式

先从控制台读取整数的个数n(n>0),然后在下一行输入n个整数,各整数间以一个空格分隔,输入的整数不会超过int的表示范围。

输出形式

先输出创建链表时总的整数比较次数,然后依次分行输出链表中前五个整数及其出现次数(整数和出现次数间以一个空格分隔);若链表中 结点的个数少于五个,则按照实际结点个数输出。

样例输入

15

-200 120 85 97 2900 85 696 -120 85 120 85 120 85 97 120

样例输出

41

120 4

97 2

85 5

-200 1

2900 1

样例说明

输入了15个整数;按照上述链表创建规则,输入第一个整数后,没有比较整数,这时总的比较次数为0;输入第五个整数后,整数比较次数为 14;输入第六个整数后,整数比较次数为17;所有整数输入完毕后,总的比较次数为41,这时整数120位于链表头,出现了4次。

评分标准

该题要求按照改进的链表查找整数,提交程序名为link.c。

问题分析

本题难度不大,按照要求模拟即可,其实在考场上我们更可能去关心的是用链表去写还是数组去实现。显然本题想考链表,但用数组去写代码肯定更简单,ds很少卡时间,唯一担心的就是会不会有某几个测试点数据量特别大,导致数组开不够大(事实上我有同学就用数组过了),所以还是建议直接用链表去实现。

具体实现过程

本题要频繁地在头结点位置插入结点,我个人喜欢带一个哑结点以简化插入结点时的逻辑,所以我们先定义结点类型,然后声明两个指针指向链表头,尾:

# include <stdio.h>
# include <stdlib.h>
typedef struct node {int num;int time;struct node* next;
} node;node* head = NULL;  // 指向链表头(哑结点)
node* tail = NULL;  // 指向表尾

在主函数中初始化:

int main()
{int n;scanf("%d", &n);head = (node*) malloc(sizeof(node));head->next = NULL;tail = head;    return 0;
}

然后进行数据的读入,每读进来一个数,我们要判断链表中是否已经有结点的数据域(num)等于该数,这需要我们把链表遍历一遍,同时设置一个flag记录是否出现过。对于没有出现过的数,只需把其插入链表尾即可;对于出现过的数,我们找到其位置p然后应该进行如下的操作:

  1. p所指的结点的time域加一;
  2. 在链表中删除p结点,这里有一个细节,如果p是尾结点的话,我们还要把tail指针前移一位,因为我们对于上述“插入表尾”的操作依赖于tail指针(当然,也可以完全不用tail指针,每次插入表尾的时候都从头把链表跑一遍也OK);
  3. 把p结点接到表头;

我们来实现这个逻辑:

    int tmp;  // 暂存读入的数据for (int i = 0; i < n; i++) {scanf("%d", &tmp);if (i==0) {  // 读入的第一个数,不用进行任何判断,直接接到head后就行tail -> next = (node*) malloc(sizeof(node));tail = tail -> next;tail -> num = tmp;tail -> time = 1;tail -> next = NULL;} else {node *p = head -> next;  // p从头到尾跑一遍,看看链表中是否出现过该数int flag = 0;  // 标志,记录是否出现过while (p) {if (p -> num == tmp) {  // p所指的结点的num域与tmp相等// 在链表中删除p结点,注意这个删除的意思不是要把p free掉if (p -> next == NULL) {  // 要是p结点是尾结点tail = find_pre(tail);  // 改变tail}p -> time ++;find_pre(p) -> next = p -> next;  // 让p的前一个结点指向后一个结点(删除p)// 把p接到head后p -> next = head -> next;head -> next = p;flag = 1;  // 标志设为1break;}p = p -> next;  // 当前结点的num域不与tmp相等,继续找下一个结点}if (!flag) {  // 没找到,把p接到表尾即可tail -> next = (node*) malloc(sizeof(node));tail = tail -> next;tail -> num = tmp;tail -> time = 1;tail -> next = NULL;}}}

其中的find_pre函数实现的功能是找到当前结点的上一个结点,对链表进行删除和插入时经常用到,其实现如下:

node* find_pre(node*p){node *q = head;while(q){if (q->next==p)return q;q=q->next;}   
}

这样我们就已经按照题目要求构建出了链表,接下来依照题意还要做两件事:

  1. 记录一共比较了多少次,只需要设置一个compare_num变量,每次从表头开始找,经过每一个结点时给其+1即可;
  2. 判断最后链表中的结点个数是否大于5,这也只需要用一个all_num变量记录,每一次在表尾插入结点时给其加一即可;

而后我们在最后先输出compare_num,再判断一下all_num是否大于5,输出对应的数据即可。

完整代码

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{int num;int time;struct node *next;
} node;node *head = NULL; // 指向链表头(哑结点)
node *tail = NULL; // 指向表尾node *find_pre(node *p)
{node *q = head;while (q){if (q->next == p)return q;q = q->next;}
}int main()
{int n;scanf("%d", &n);head = (node *)malloc(sizeof(node));head->next = NULL;tail = head;int tmp;              // 暂存读入的数据int all_num = 1;      // 记录总的结点个数int compare_time = 0; // 记录比较的次数for (int i = 0; i < n; i++){scanf("%d", &tmp);if (i == 0){ // 读入的第一个数,不用进行任何判断,直接接到head后就行tail->next = (node *)malloc(sizeof(node));tail = tail->next;tail->num = tmp;tail->time = 1;tail->next = NULL;}else{node *p = head->next; // p从头到尾跑一遍,看看链表中是否出现过该数int flag = 0;         // 标志,记录是否出现过while (p){compare_time++;if (p->num == tmp){ // p所指的结点的num域与tmp相等// 在链表中删除p结点,注意这个删除的意思不是要把p free掉if (p->next == NULL){                          // 要是p结点是尾结点tail = find_pre(tail); // 改变tail}p->time++;find_pre(p)->next = p->next; // 让p的前一个结点指向后一个结点(删除p)// 把p接到head后p->next = head->next;head->next = p;flag = 1; // 标志设为1break;}p = p->next; // 当前结点的num域不与tmp相等,继续找下一个结点}if (!flag){ // 没找到,把p接到表尾即可all_num++;tail->next = (node *)malloc(sizeof(node));tail = tail->next;tail->num = tmp;tail->time = 1;tail->next = NULL;}}}// 输出printf("%d\n", compare_time);if (all_num < 5){node *temp = head->next;while (temp){printf("%d %d\n", temp->num, temp->time);temp = temp->next;}}else{node *temp = head->next;for (int i = 0; i < 5; i++){printf("%d %d\n", temp->num, temp->time);temp = temp->next;}}return 0;
}

这篇关于BUAA数据结构期中考试2023的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/326917

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【数据结构入门】排序算法之交换排序与归并排序

前言         在前一篇博客,我们学习了排序算法中的插入排序和选择排序,接下来我们将继续探索交换排序与归并排序,这两个排序都是重头戏,让我们接着往下看。  一、交换排序 1.1 冒泡排序 冒泡排序是一种简单的排序算法。 1.1.1 基本思想 它的基本思想是通过相邻元素的比较和交换,让较大的元素逐渐向右移动,从而将最大的元素移动到最右边。 动画演示: 1.1.2 具体步