文章目录
- 数据结构篇
- 数组
- 字符串
- 链表
- 树
- 图
- 堆
- 算法篇
- 哈希
- 查找
- 排序
- 数据库篇
- SQL语言篇
数据结构篇
数组
省流:
- 计算二维数组指定元素的位置
- 压缩矩阵
1. 执行以下代码段(程序已包含所有必需的头文件)会输出什么结果。
char a[] = "abcd", b[10] = "abcd";
printf("%d, %d", sizeof(a), sizeof(b));**
- 解答:5,10
- 分析:字符串“abcd”占用5个字节,因为包含结束符’\0’,初始化时未指定数组a的大小,所以sizeof(a)为5。数组b初始化时指定了长度10,所以sizeof(b)为10。
- 知识:
处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的末尾,就结束处理。'\0'至关重要,没有'\0'就意味着永远也到达不了字符串的结尾。
2. 采用压缩存储之后,下三角矩阵的存储空间可以节约一半,这样的说法正确吗?
- 解答:不完全正确
- 分析:对于NxN的二维下三角矩阵,采用压缩后,只需要(N+1)*N/2。当N趋于无穷大的时候,就是约为1/2。而且你说2x2的矩阵有压缩的必要吗?就是因为矩阵大了才需要压缩。
3. 数组元素的下标值越大,存取时间越长,这样的说法正确吗?
- 解析:不正确
- 分析:数组存取采用首地址加上元素所在位置元素大小计算(行优先或者列优先)其所在地址 假设一个数组为a[10][10] 数组a[0][0]地址为0x00,采用行优先存储,元素占4个字节 a[i][j]的地址为0x00+(i10+j)*4 所以不会因为数组过长而导致存取时间变长
4. 稀疏矩阵一般的压缩存储方式有两种,即 三元组和十字链表
5. 线性表的长度是线性表所占用的存储空间的大小
- 解析:错误
- 分析:线性表长度的定义是它所包含的元素的个数。元素的类型决定了元素所占用存储空间的大小,但元素的个数不等价于元素的类型。
6. 从一个无序数组中挑选出其中前十个最大的元素,在以下的排序方法中最快的方法是
- 解析:堆排序
- 分析:用堆排序最好,因为堆排序不需要等整个排序结束就可挑出前50个最大元素,而快速排序和基数排序都需等待整个排序结束才能知道前50个最大元素。
7. 数组与链表的区别是
- 解析:前者长度固定,后者长度可变
- 分析:前者长度固定,后者长度可变
8. 假设以数组Data[0…m-1]存放循环队列的元素,其头尾指针分别为front和rear,则当前队列中的元素个数为
- 解析:(rear-front+m) % m
9. 执行以下代码段(程序已包含所有必需的头文件)会输出什么结果。
char a[2][3] = {{'a', 'b', 'c'}, {'1', '\0', '2'}};
printf("%d", sizeof(a));
- 解析:6
- 分析:二维数组a初始定义两行三列,所以其占用内存空间大小为6,与其赋值无关
10. 将数组 var a=[1,2,3] 变成数组 [4,3,2,1] 下面的方式正确的是?
- 解析:a.reverse().unshift(4)、a.push(4); a.reverse()
- 分析:学习Array数组的常用方法 参考文章
11. 有一个100*90的稀疏矩阵,非0元素有10个,设每个整型数占2字节,则用三元组表示该矩阵时,所需的字节数是
- 解析:66
- 分析:将非零元素所在行、列、非零元素的值构成一个三元组(i,j,v) ;每个非零元素占32=6个字节,共10个非零元素,需610 = 60 个字节;此外,还一般要用三个整数来存储矩阵的
行数、列数和总元素个数
,又需要3*2 = 6个字节;总共:60 + 6 = 66 个字节。
字符串
省流:
- '\0’结束符作为字符串的结尾
- sizeof是所在内存大小,len是元素个数
1. 观察下列代码,分析结果
String s1 = "coder";
String s2 = "coder";
String s3 = "coder" + s2;
String s4 = "coder" + "coder";
String s5 = s1 + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s4 == "codercoder");
- 解析:false、false、true
- 分析:
2. 观察下面程序,程序运行输出的结果是
char[] f = {'N','O','W','C','O','D','E','R'};
String st = new String(f,2,5);
System.out.println(st);
- 解析:WCODE
- 分析:String str = new String (String str,int index,int length);
3. 假设字符串char a[] = “abc123”,char b[] = “xyz”,那么使用字符串连接函数strcat(a, b)连接字符串a和b之后得到的结果是
- 解析:内存溢出
- 分析:strcat(char* strDestination, const char* strSource);把strSource追加到 strDestination结尾,所以必须要保证 strDestination 有足够的内存空间来容纳两个字符串,否则会导致溢出错误。
4. 执行以下代码段(程序已包含所有必需的头文件)会输出什么结果。
char a[] = "abc";
char b[] = {'a', 'b', 'c'};
printf("%d, %d", sizeof(a), sizeof(b));
- 解析:4,3
- 分析:数组a是通过字符串赋值方式,数组b是采用单个字符逐个赋值的方式。
不同的是数组a的长度是4个字符,而数组b的长度为3个字符,因为字符串后面会有一个’\0’作为结束符。
5. 设串 s1=“ABCDEFG”, s2=“PQRST” ,函数 con(x,y) 返回 x 和 y 串的连接串, subs(s, i, j) 返回串 s 的从序号 i 开始的 j 个字符组成的子串, len(s) 返回串 s 的长度,则 con(subs(s1, 2, len(s2)), subs(s1, len(s2), 2)) 的结果串是(本题“序号”概念从1开始)
- 解析:BCDEFEF
-分析:sizeof是所在内存大小,len是元素个数
6. 哪个是不正确的字符常量
- 解析:ABCD
- 分析:四个答案都采用的是双引号关闭,所以是字符串常量而不是字符常量。
7. 子串 “ABC” 在主串 “AABCABCD” 中的位置为 2(序号从 0 开始)
- 解析:错误
- 分析:从0开始的下标,所以是,1
8. 在 C/C++ 中,有字符数组 a[80] 和 b[80],则正确的输出语句是
- 解析:puts(a);puts(b);
- 分析:
puts(String str)只能输出单个字符串
printf(“%s,%s”,a,b)
putchar(char a)只能输出单个字符
9. 已知串 S= "babab ", 其 Next 数值序列(模式匹配)为
- 解析:01123
- 分析:
首先介绍2个概念,字符串的前缀和后缀(这里的前缀是不包括最后一个字符的子串,后缀是不包含第一个字符的子串)。
拿题目中的字符串a='‘babab’'举例,
首先第一位0,第二位1。这个是固定的。
第三位,字符串是“bab”,这时候“bab”的前缀有b,ba;后缀有ab,b,可以看出前后缀相等的最长的字符串只有b,因为b的长度是1,所以这里第三位的next值就是1。
到了第四位,字符串是“baba”,前缀是b,ba,bab;后缀是aba,ba,a。这里可以看出前后缀相等的最长的字符串是ba,长度是2,因此第四位的next值是2。
到了第五位,字符串是“babab”,前缀是b,ba,bab,baba;后缀是abab,bab,ab,b。这里可以看出前后缀相等的最长的字符串是bab,长度是3,因此第五位的next值是3.
因此综合起来next值就是0 1 1 2 3
链表
1. 某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用()存储方式最节省运算时间
- 解析:仅有尾指针的单循环链表
2. 邻接表是图的一种顺序存储结构,这种说法
- 解析:错误
- 分析:邻接表指的是:为图的每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(对于有向图是以Vi为尾的弧)。
3. 广义表K=(m,n,(p,(q,s)),(h,f)),则head[tail[head[tail[tail(K)]]]]的值为
- 解析:q
- 分析:
head() 返回列表的第一个元素;
tail() 返回列表的删去第一个元素之后的剩余列表;
K=(m,n,(p,(q,s)),(h,f)),
head[tail[head[tail[tail(K)]]]]
tail(K)-------(n,(p,(q,s)),(h,f))
tail[tail[K]]--------((p,(q,s)),(h,f))
head()-----(p,(q,s))
tail()-----(q,s)
head()-------q
4. 某带链的队列初始状态为 front=rear=NULL 。经过一系列正常的入队与退队操作后, front=rear=10 。该队列中的元素个数为
- 解析:1
- 分析:
带链的队列,由于每个元素都包含一个指针域指向下一个元素,当带链队列为空时 front=rear=Null ,插入第 1 个元素时, rear+1 指向该元素, front+1 也指向该元素,插入第 2 个元素时 rear+1 , front 不变,删除 1 个元素时 front+1 。即 front=rear 不为空时带链的队列中只有一个元素。
5. 以下关于单向链表说法正确的是
- 解析:ABC
- 分析:
树
(森林、树、二叉树、二叉排序树、二叉平衡树、二叉线索树、B树、B+树、红黑树)
1. 某二叉树的中序序列为 BDCA ,后序序列为 DCBA ,则前序序列是
- 解析:ABCD
- 分析:本题中中序序列为 BDCA ,后序序列为 DCBA, 可知 A 为根结点, BDC 为左侧结点
总结:从先序或后序得到根,从中序将根、左、右划分
2. 下面序列哪个不可能是二叉搜索时的后序遍历结果
- 解析:35142
- 分析:由于二叉搜索树满足:左孩子 < 根节点 < 右孩子
因此若后序遍历二叉搜索树,首先,最后一个结点肯定是根节点。根节点将序列分为两部分,前一部分比根节点小,后一部分比根节点大。或者都比根节点小(大),此种情况为无右(左)子树。
3. 将森林F转换为对应的二叉树T,F中叶结点的个数等于
- 解析:T中左孩子指针为空的结点个数
- 分析:树、二叉树、森林的转换
树转二叉树,树的孩子结点转为左子树,树的兄弟结点转为右子树,那么反过来就是二叉树没有左子树的结点是树的叶子。
4. 已知中序遍历的序列为abcdef,高度最小的可能的二叉树的叶子是
- 解析:ace、acf、adf
- 分析:ABC 高度最小的二叉树是平衡二叉树,也就是c为根节点或者d为根节点 当c为根节点时,左子树的叶子节点可能是a或者b中的一个,右子树的叶子节点是d和f,可能是adf或者bdf 当d为根节点时,左子树的叶子节点可能是a和c,右子树的叶子节点是e或f中的一个,可能是ace或者acf
5. 一棵二叉树共有 25 个结点,其中 5 个是叶子结点,则度为 1 的结点数为
- 解析:16
- 分析:二叉树的5个特性
6. Huffman 树的带权路径长度WPL等于
- 解析:各叶子结点的带权路径长度之和
7. 将一棵树t 转换为孩子—兄弟链表表示的二叉树h,则t的后根序遍历是h 的
- 解析:中序遍历
- 分析:
图
1. 一个具有8个顶点的连通无向图(没有自环),最多有()条边
- 解析:28
- 分析:8个点中任选择两个, 都可以有一条边, 最多 8 * 7 / 2 = 28
2. 设某无向图有n个顶点,则该无向图的邻接表中有()个表头结点
- 解析:n
- 分析:无向图的邻接表中,每个顶点作为一个表头,就可建立邻接表,所以表头有n个
3. 下面关于求关键路径的说法不正确的是()
- 解析:一个事件的最迟开始时间为以该事件为尾的弧的活动最迟开始时间与该活动的持续时间的差
-分析:一个事件的最迟开始时间为以该事件为尾的弧的活动最迟开始时间与该活动的持续时间的和
4. 有向图 G 中有 n 个顶点,e 条边,采用邻接表存储,若采用 BFS 方式遍历其时间复杂度为
- 解析:O( n+e )
- 分析:对于DFS,BFS遍历来说,时间复杂度和存储结构有关:
- 若采用邻接矩阵存储,时间复杂度为O(n^2);
- 若采用邻接链表存储,时间复杂度为O(n+e) = 顶点访问时间O(V)+边访问时间O(E)
5. 图的Depth-First Search(DFS)遍历思想实际上是二叉树()遍历方法的推广
- 解析:先序
6. 下列 AOE 网表示一项包含 8 个活动的工程。通过同时加快若干活动的进度可以缩短整个工程的工期。下列选项中,加快其进度就可以缩短工程工期的是( )
- 解析:f和d
- 分析:
acg-18
aeh-18
bdcg-27
bdeh-27
bfh-27
所以只有c选项才能同时缩短三条长度为27的路径。
7. 在图 G 的最小生成树 G1 中,可能会有某条边的权值超过未选边的权值
- 解析:正确
- 分析:因为有些边虽然小,但是都拿小边就会回环。有些边虽然大,但是不拿大边就会连接不了其他节点
堆
注意:堆存放在数组中,以完全二叉树的形式呈现
1. 在堆排序的过程中,建立一个堆的时间复杂度是
- 解析:O(n)
- 分析:
建堆:把数据放到数组后面,时间复杂度为O(n)
调整堆、插入、删除:把一个节点往下一直调整,时间复杂度为O(log2n)
堆排序:把所有节点往下一直调整,时间复杂度为O(nlog2n)
算法篇
哈希
1. 哈希查找中k个关键字具有同一哈希值,若用线性探测法将这k个关键字对应的记录存入哈希表中,至少要进行()次探测
- 解析:k(k+1)/2
- 分析:
问的是“至少”,那么设表原来为空表。
第一个:直接找到坑,入坑,1次;
第二个:和第一个同hash,找到坑被第一个给占了,找下一个,入坑,2次;
第三个:第一个被占了,第二个也被占了,找第三个,入坑,3次;
。。。
第n个:n次;
一共:(1+n)*n / 2 次
【开放地址法(除了随机探测)都是(1+n)*n / 2 次】
2. 设有n个关键字具有相同的Hash函数值,则用线性探测法把这n个关键字映射到Hash表中需要做几次线性探测?
- 解析:n*(n-1)/2
- 分析:第一个关键字直接插入,第二个关键字要做1次探测,所以类推n个关键词要做0+1+2+…+(n-1) = n*(n-1) / 2
3. 采用线性探测法处理散列时的冲突,当从哈希表删除一个记录时,不应将这个记录的所在位置置空,因为这会影响以后的查找
- 解析:正确
4. 以下哪个不属于单向哈希表的特征(假设没有冲突)
- 解析:它把固定的信息转换成任意长度信息输出
- 分析:hash函数可以把字符串等任意长度的输入映射成固定长度的整数,也就是哈希值 B。上述说法恰好相反
5. 一个线性序列(30,14,40,63,22,5),假定采用散列函数Hash(key)=key%7来计算散列地址,将其散列存储在A[0~6]中,采用链地址法解决冲突。若查找每个元素的概率相同,则查找成功的平均查找长度是
- 解析:4/3
- 分析:
官方解析:
30%7=2,查找次数为1,
14%7=0,查找次数为1,
40%7=5,查找次数为1,
63%7=0,查找次数为2,
22%7=1,查找次数为1,
5%7=5,查找次数为2,
平均查找长度为(1+1+1+2+1+2)/6=4/3
6. 设某散列表的长度为1000,散列函数为除留余数法,H(K)=K%P,则P通常情况下最好选择
- 解析:997
- 分析:小于等于表长的最大质数
查找
1. 具有12个关键字的有序表,折半查找的平均查找长度()
- 解析:3.1
- 分析:将12个数画成完全二叉树,第一层有1个、第二次2个、第三层4个,第四层只有5个。
二分查找时:
第一层需要比较1次
第二两个数,每个比较2次
第三层四个数,每个比较3次
第四层五个数,每个比较4次
则平均查找长度即为:(1+22+34+4*5)/12 = 37/12 = 3.0833 即为 A、3.1
2. 有一个有序表为{1,3,9,12,32,41,45,62,75,77,82,95,100},当折半查找值为82的结点时,____次比较后查找成功。
- 解析:4次
- 分析:
一共13个数 下标为0-12
第一次查找 用left+right即(0+12)/2=6 找到下标为6的数45 因为目标数82>45 所以left+1
第二次查找 left变为6+1=7 left+right(7+12)/2=9 找到下标为9的数 77 因为目标数82>77 所以left+1
第三次查找 left变为9+1=10 left+right(10+12)/2=11 找到下标为11的数95 因为目标数82<95 所以left-1
第四次查找 left变为(11-1)=10 而right变为95的下标数11 left+right为(10+11)/2=10 找到下标为10的数82 与目标数相等 所以查询四次
排序
1. 对关键码序列28,16,32,12,60,2,5,72快速排序(最常用的快速排序,以第一个关键码为基准),使用挖坑法,从小到大一次划分结果为()
- 解析:5,16,2,12,28,60,32,72。
- 分析:
2. 对以下关键字序列用快速排序法进行排序,速度最慢的是- 解析:4,8,16,20,24,29
- 分析:因为已经有序,快速排序的重点就在于能把序列分成两部分,这样才能让每个元素比较次数从n变成log n,如果有序了(顺序或逆序),都无法分成两部分,每次都只有一部分。
3. 下面说法错误的是()
- 解析:c
- 分析:
A:快速排序平均时间复杂度为O(nlogn),插入排序平均时间复杂度为O(n^2),正确
B:堆排序每次会使当前最后一个位置上的元素归位,正确
C:使用选择排序最快,错误
D:插入排序是稳定排序,正确
4. 下面哪种排序的平均比较次数最少()
- 解析:插入、选择、堆、快速排序,选择快速排序
- 分析:快排和堆排都是O(nlogn)级别,但快排的平均比较次数大概是1.39nlogn,而堆排序大概是2nlogn,所以快排的更少。因为堆排序要重新构建堆,所以需要更多次比较。
5. 最坏情况下 insert sort, quick sort ,merge sort 的复杂度分别是多少
- 解析:O(nn),O(nn),O(nlogn)
- 分析:注意是最坏情况
数据库篇
1. 下列不属于触发事件的是
- 解析:AFTER、UPDATE、DELETE、INSERT,选择AFTER
- 分析:AFTER触发器又称后触发器,在执行了INSERT、UPDATE、DELETE语句操作之后执行AFTER触发器。
SQL语言篇
select
字段列表
from
表名列表
where在分组之前进行限定,如果不满足条件,则不参与分组
不可以跟聚合函数
条件列表
group by
分组字段
having在分组之后进行限定,如果不满足结果,则不会被查询出来
可以跟聚合函数
分组之后的条件
order by
排序
limit
分页限定
1. 在gameList表中(player_id, event_date)是主键,如何查找出每个player_id的第一次登录的时间(event_date)
- 解析:SELECT player_id, min(event_date) as first_login FROM gameList GROUP BY player_id
- 分析:group by的用法,在另一篇博客有记录
2. 小李在创建完一张数据表后,发现少创建了一列,此时需要修改表结构,应该用哪个语句进行操作?
- 解析:ALTER TABLE
- 分析:
添加列: ALTER TABLE 表名 add 字段名
修改列: ALTER TABLE 表名 modify 字段名
删除列: ALTER TABLE 表名 drop 字段名