GESP2025年3月认证解析
GESP一级
一、单选题
- 答案:D
- 解析:DeepSeek 是字节跳动公司开发的人工智能,它具备生成文本的能力,所以可以根据《哪吒 2》的场景生成剧情脚本。A 选项中《哪吒 2》是贺岁片,并非新型操作系统;B 选项 DeepSeek 不是深海钻探软件;C 选项《哪吒 2》是电影,不能生成新的软件 。
- 答案:D
- 解析:在集成开发环境中编辑源代码文件时,可以修改变量定义、保存代码修改以及撤销代码修改操作。但插入执行截图并非在编辑源代码文件时能直接进行的操作,执行截图一般是在程序运行后通过其他工具获取 。
- 答案:D
- 解析:C++ 中变量命名规则为:只能由字母、数字和下划线组成,且不能以数字开头。A 选项中包含 “-”,不符合规则;B 选项以 “$” 开头,不合法;C 选项包含 “%%”,不符合要求;D 选项 “_Var_1” 符合变量命名规则 。
- 答案:C
- 解析:do 是 C++ 语言的关键字,用于构成 do - while 循环结构。A 选项 abs 是 C++ 标准库中的函数,用于求绝对值;B 选项 cin 是输入流对象,用于从输入设备读取数据;D 选项 endl 是用于输出换行并刷新缓冲区的操纵符,它们都不是关键字 。
- 答案:C
- 解析:A 选项中,do - while 循环需要有循环体内容,此处循环体为空,且 break 不能直接用于 do - while 循环外,编译不通过;B 选项 for 循环中,break 不能直接用于 for 循环外,编译不通过;C 选项 if 语句中可以使用 break 跳出 switch、循环等结构,这里虽然 break 跳出 if 语句没有实际意义,但语法上可以通过编译;D 选项 switch 语句中,break 通常用于跳出 switch 结构,但此处 switch 没有 case 分支,且 break 直接在 switch 外,编译不通过 。
- 答案:B
- 解析:printf 函数中,“%02d” 表示输出的整数不足两位时在前面补 0,“%2d” 表示输出的整数宽度为 2,不足两位时右对齐。A 选项 “%2d%02d” 输出结果为 “__ 322”;B 选项 “%02d%2d” 输出结果为 “__ 0322”;C 选项 “%02d%02d$\(”多了两个“\)”,输出结果为“__ 0302$\(”;D 选项 “\_\_\_\_ %02d%02d\)”多了下划线,输出结果为“____ 0302$” 。
- 答案:C
- 解析:C++ 中,字符串需要用双引号括起来,单引号用于表示字符。将双引号改为两个单引号会导致语法错误,代码无法正确执行。A 选项将汉字改为英文 “Hello”,代码能正确执行;B 选项改为 “Hello 代码!”,代码也能正确执行;D 选项将双引号改为三个双引号,虽然不符合常规用法,但在一些编译器中可能不会报错(取决于具体编译器对字符串字面量的处理方式),但不推荐这样使用 。
- 答案:D
- 解析:根据运算符优先级,先进行除法运算 16 / 4 = 4,再进行取模运算 4 % 2 = 0 。
- 答案:D
- 解析:已知 N = 12,N % 3 = 0,N / 5 = 2(整数除法结果取整),所以 N % 3 + N / 5 = 0 + 2 = 2 。
- 答案:D
- 解析:printf 函数中,“% d” 用于输出整数,这里 {N} 和 *{N} 不会被替换,直接输出,后面的 “% d” 会被 N 的值替换,所以输出为 “{N}{N}={1010}” 。
- 答案:D
- 解析:输入 100 和 200 后,first = 100,second = 200,first /second = 0(整数除法,100 除以 200 结果取整为 0),0 * 200 = 0 。
- 答案:C
- 解析:A 选项 “(i % 2 == 0) && (i % 7 == 2)” 表示 i 能被 2 整除且除以 7 余数为 2;B 选项 “(!(i % 2)) && (i % 7 == 2)”,“!(i % 2)” 等价于 “i % 2 == 0”,同样表示 i 能被 2 整除且除以 7 余数为 2;D 选项 “(i % 2 != 1)” 也等价于 “i % 2 == 0”,表示 i 能被 2 整除且除以 7 余数为 2;C 选项 “(!(i % 2)) && (!(i % 7))” 表示 i 能被 2 整除且能被 7 整除,不符合能被 2 整除且除以 7 余数为 2 的要求 。
- 答案:B
- 解析:在 for 循环中,i 从 -1000 到 999,对于每一个正数 i,都有对应的负数 -i,它们相加为 0,所以 tnt 最终结果为 0 。
- 答案:B
- 解析:for 循环中,i 从 1 开始,每次增加 5,当 i = 100 时,不满足 i < 100 的条件,循环结束,此时 i 的值为 100 。
- 答案:D
- 解析:for 循环中,i 从 5 开始,每次增加 5。当 i 为偶数时执行 continue 跳过本次循环;当 i 能同时被 3 和 7 整除时执行 break 结束循环。在 i < 100 的范围内,i = 15 时能同时被 3 和 7 整除,在这之前,i = 5、10 时因是偶数跳过,只有 i = 15 满足条件进入循环体执行 tnt += 1,所以 tnt 最终值为 1 。
二、判断题
- 答案:正确
- 解析:C++、Python 等高级编程语言编写的程序,最终都需要通过编译器或解释器转化为机器指令,才能在计算机硬件上运行 。
- 答案:错误
- 解析:当 N 为正整数时,N * 2 % N 的结果为 0。例如,当 N = 3 时,3 * 2 % 3 = 6 % 3 = 0 。
- 答案:错误
- 解析:代码中定义的 N 是 char 类型,而使用 “% d” 格式化输出,会导致类型不匹配。并且从键盘输入 10 时,字符‘1’和‘0’会被存储到 char 类型的 N 中,无法得到预期的结果 20 。
- 答案:错误
- 解析:删除 continue 后,程序在遇到偶数时不会跳过本次循环后面的语句,会继续执行 “printf ("奇数");”,改变了程序的执行逻辑和输出结果 。
- 答案:错误
- 解析:在 C++ 中,“_” 可以作为合法的变量名,但不建议单独使用,因为在某些系统头文件中可能有特殊含义,但从语法角度是可以作为变量名的 。
- 答案:错误
- 解析:for 循环中,i 从 3 开始,每次增加 2,当 i = 3 时,满足 i < 5 的条件,输出 3,然后 i 变为 5,不满足 i < 5 的条件,循环结束,所以只会输出 3 。
- 答案:错误
- 解析:当 i = 0 时,0 * 2 = 0,0 * 0 = 0,i * 2 <i * i 为 false;当 i = 1 时,1 * 2 = 2,1 * 1 = 1,i * 2 < i * i 为 false;当 i = 2 时,2 * 2 = 4,2 * 2 = 4,i * 2 < i * i 为 false;当 i> 2 时,i * 2 < i * i 为 true,所以输出的 true 个数小于 7 个 。
- 答案:错误
- 解析:user - Name 中包含 “-”,不符合 C++ 变量命名规则,不能作为合法变量名,user_Name、_userName、userName_是合法变量名 。
- 答案:错误
- 解析:C++ 中 continue 语句用于结束本次循环,直接进入下一次循环;break 语句才可以提前结束循环 。
- 答案:错误
- 解析:scanf 函数中使用 “% d” 读取输入,输入 3.6 时,只会读取整数部分 3 赋给 N,N / 3 * 5 = 3 / 3 * 5 = 1 * 5 = 5 。
GESP二级
一、单选题
- 答案:D
- 解析:DeepSeek 是人工智能,具备文本生成能力,能够根据《哪吒 2》场景生成剧情脚本。A 选项中,《哪吒 2》是电影并非操作系统;B 选项,DeepSeek 不是深海钻探软件;C 选项,《哪吒 2》不具备生成软件的功能 。
- 答案:C
- 解析:在流程图中,圆形框是起止框,用于表示流程的开始和结束;椭圆形框不是标准流程图符号;菱形框是判断框,用于根据条件进行判断分支;平行四边形框是输入输出框,输出语句应放在平行四边形框中。
- 答案:A
- 解析:代码中 “a == b” 和 “b == a” 是关系判断表达式,它们不会改变 a 和 b 的值。a 初始值为 3,b 初始值为 4,所以输出是 3 4 。
- 答案:A
- 解析:原代码通过取余判断彩球颜色,在最后一个判断分支中,“remainder == 9 || remainder == 0” 涵盖了编号对 10 取余为 9 和 0 的情况,用 else 可以简化代码,效果相同。B 选项修改后,“remainder <= 5” 会将余数为 0 - 5 的都判定为红色,不符合题目要求;C 选项 “6 <= remainder <= 8” 在 C++ 中不是合法的条件判断写法;D 选项 “remainder = N / 10” 计算的不是余数,不符合题意 。
- 答案:D
- 解析:在 for 循环中,“i % 3” 表示 i 除以 3 的余数,当余数不为 0 时(即 i 不能被 3 整除),tnt 加 1;当余数为 0 时(即 i 能被 3 整除),tnt 加 2。从 0 到 9 循环,能被 3 整除的数有 0、3、6、9,共 4 个,这 4 个数使 tnt 每次加 2;不能被 3 整除的数有 6 个,这 6 个数使 tnt 每次加 1。所以 tnt = 6×1 + 4×2 = 14 。
- 答案:A
- 解析:for 循环中遇到 break 语句会立即终止循环。在 “for (i = 10; i> 0; i -= 2)” 循环中,第一次循环 i = 10,执行 break 后循环结束,此时 i 的值仍为 10 。
- 答案:D
- 解析:在 for 循环中,当 i 能被 3 整除时执行 continue,跳过本次循环后面的输出语句。所以输出的是 i 不能被 3 整除时的 “0#”。当 i 从 0 到 9 循环结束后,i = 10,满足 “i >= 10” 条件,会输出 “1#” 。
- 答案:D
- 解析:外层 for 循环控制 i 从 0 到 4,内层 for 循环控制 j 从 i 到 1(当 i = 0 时,内层循环不执行)。当 i = 1 时,j 从 1 到 1,输出 1;当 i = 2 时,j 从 2 到 1,输出 2 - 1;当 i = 3 时,j 从 3 到 1,输出 3 - 2 - 1;当 i = 4 时,j 从 4 到 1,输出 4 - 3 - 2 - 1。整体输出为 0 - 0 - 1 - 0 - 1 - 2 - 0 - 1 - 2 - 3 。
- 答案:C
- 解析:A 选项 “(i % 2 == 0) && (i % 7 == 2)” 表示 i 能被 2 整除且除以 7 余数为 2;B 选项 “(!(i % 2)) && (i % 7 == 2)”,“!(i % 2)” 等价于 “i % 2 == 0”,同样表示 i 能被 2 整除且除以 7 余数为 2;D 选项 “(i % 2 != 1)” 也等价于 “i % 2 == 0”,表示 i 能被 2 整除且除以 7 余数为 2;C 选项 “(!(i % 2)) && (!(i % 7))” 表示 i 能被 2 整除且能被 7 整除,不符合能被 2 整除且除以 7 余数为 2 的要求 。
- 答案:A
- 解析:外层 for 循环遍历 1 到 N 的数,内层 while 循环用于判断每个数中是否含有 3。当 j 的个位数是 3 时,cnt 加 1,然后继续判断 j 去掉个位数后的数,所以使用 continue 跳过本次 while 循环剩余部分,并用 “j /= 10” 去掉 j 的个位数 。
- 答案:C
- 解析:实现 1 中,通过 last *= i 不断利用前一次计算的结果计算阶乘,每次循环只进行一次乘法和一次加法,计算量较小,效率高;实现 2 中,每次计算 i 的阶乘都要重新从 1 开始累乘,计算量较大。A 选项说法错误,实现 1 效率高;B 选项实现 2 效率不如实现 1,且代码相对复杂;D 选项两种实现效率差异明显 。
- 答案:D
- 解析:A 选项 “isPrime (j) && isPrime (i - j)” 和 “isPrime (j) == true && isPrime (i - j) == true” 效果相同,都是判断 j 和 i - j 是否都为质数;B 选项因为内层循环 j 从 2 开始递增,所以输出的一对质数一定是小的数在前;C 选项代码只是验证有限范围内的偶数,不能从数学上证明哥德巴赫猜想;D 选项 break 语句在 if 语句块内,当找到一组满足条件的质数时跳出内层循环,若移到 if 语句块外会导致只要 j 从 2 开始遍历到第一个质数就跳出循环,无法正确验证所有可能的组合,所以该说法错误 。
- 答案:B
- 解析:A 选项 printf ("\n") 可以输出换行;B 选项 “last += 1” 和 “last = last + 1” 执行效果相同,都是将 last 的值加 1;C 选项 “j < i + 1” 控制每行输出的数字个数,修改为 “j < i” 会少输出一个数字,不符合输出要求;D 选项外层 for 循环前的 “last = 1” 修改为 “last = 0”,会导致输出的起始数字变为 0,执行效果不同 。
- 答案:C
- 解析:rand () 函数生成的是 0 到 RAND_MAX 之间的随机整数。“rand () % 10 + 1” 可以生成 1 到 10 之间的随机整数,“rand () % 11” 生成的是 0 到 10 之间的随机整数,“rand () % 10” 生成的是 0 到 9 之间的随机整数,“rand () % 9 + 1” 生成的是 1 到 9 之间的随机整数 。
- 答案:C
- 解析:判断两个 float 类型变量是否相等,需要考虑精度问题。因为 a 和 b 可能存在微小差异,所以要用绝对值判断它们的差值是否在允许的精度范围内。A 选项只考虑了 b - a 小于 0.000001 的情况,没有考虑 a - b 的情况;B 选项同理,没有考虑绝对值;D 选项 sqrt 函数用于计算平方根,不适合判断两个数是否相等 。
二、判断题
- 答案:正确
- 解析:C++、Python 等高级编程语言编写的程序,最终都要经过编译器或解释器转换为机器指令,才能在计算机硬件上运行 。
- 答案:正确
- 解析:对于正整数 N,N / 10 会取整,N - N / 10 * 10 相当于 N 减去 N 的十位及以上的数,结果就是 N 的个位数;N % 10 直接计算 N 除以 10 的余数,也是 N 的个位数 。
- 答案:错误
- 解析:在 C++ 中,“10 <= N <= 12” 这种写法不能正确判断 N 是否在 10 到 12 之间。它会先计算 “10 <= N”,结果为 0(假)或 1(真),然后再用这个结果与 12 比较,无法得到正确的判断结果。应改为 “(10 <= N) && (N <= 12)” 。
- 答案:错误
- 解析:由于浮点数的精度问题,对于正整数 N,(sqrt (N) * sqrt (N)) 不一定严格等于 N。例如当 N = 2 时,sqrt (2) 在计算机中是一个近似值,sqrt (2) * sqrt (2) 得到的结果与 2 可能存在微小差异,不会严格相等 。
- 答案:错误
- 解析:代码中执行 “a = a - b” 后,a = -1;执行 “b = a + b” 后,b = 2;执行 “a = b - a” 后,a = 3。所以最终输出 “3 * 2 = 6” 是错误的,实际输出应该是 “3 * 2 = 6”(这里是根据错误代码逻辑分析出的输出,并非正确结果,因为代码逻辑本身错误) 。
- 答案:错误
- 解析:在 for 循环中,continue 语句之后的代码在本次循环中不会执行,所以 “cout << i << endl;” 不会被执行,不会输出 10 。
- 答案:正确
- 解析:在 for 循环中,先执行 break 语句,会跳出整个 for 循环,continue 语句不会执行。此时 i 的值为 1,所以最终输出 1 。
- 答案:错误
- 解析:外层 for 循环 i 从 0 到 4,当 i = 0 时,内层 for 循环 “for (int j = 0; j < i; j++)” 条件不满足,不执行循环体;当 i = 1 时,内层循环执行 0 次;当 i = 2 时,内层循环执行 1 次;当 i = 3 时,内层循环执行 2 次;当 i = 4 时,内层循环执行 3 次。总共输出 “OK” 的次数为 1 + 2 + 3 = 6 次 。
- 答案:错误
- 解析:原代码 “for (int i = 1; i < 5; i++)” 从 1 开始累加,结果为 1 + 2 + 3 + 4 = 10;若改为 “for (int i = 0; i < 5; i++)”,则从 0 开始累加,结果为 0 + 1 + 2 + 3 + 4 = 10,但循环执行过程和含义不同,所以输出结果相同但本质有区别 。
- 答案:错误
- 解析:外层 for 循环 i 从 0 到 4,内层 for 循环 “for (i = 0; i < i; i++)” 条件 “i < i” 始终不成立(因为 i 在进入内层循环时与自身比较),所以内层循环不会执行。外层循环每次执行完内层循环(实际未执行)后,输出 i 的值,所以输出为 0 1 2 3 4 。
GESP三级
一、单选题
- 答案:D
- 解析:因为 Base64 编码是每 3 字节输入数据编码为 4 字节输出数据。10 字节的输入数据,10÷3 = 3 余 1,即完整的 3 字节有 3 组,这 3 组会编码成 3×4 = 12 字节。剩下 1 字节,按照规则会用 “=” 号填充,使其凑足 4 字节(实际是 2 个 “=” 号,占 2 字节),所以总共编码后的字符串长度是 12 + 4 = 16 字节。
- 答案:B
- 解析:根据 UTF - 8 编码规则,0xF0 对应二进制是 11110000,属于 4 字节编码的起始字节,后面跟着 3 个以 10 开头的字节(0x90 对应 10010000,0x80 对应 10000000,0x80 对应 10000000 ),符合 4 字节编码格式。A 选项 0xC0 对应 11000000,是 2 字节编码的起始字节,但后面只有 1 个字节,不符合规则;C 选项 0x80 不能作为 UTF - 8 编码的起始字节;D 选项 0xFF 对应 11111111,0xFE 对应 11111110,0xFD 对应 11111101,都不符合 UTF - 8 编码规则。
- 答案:A
- 解析:八进制数 -5 转换为十进制是 -5,在 8 位二进制原码表示中,最高位为符号位,负数的符号位是 1,数值部分是 5 的二进制表示 0000101,所以 -5 的二进制原码是 10000101。
- 答案:A
- 解析:将十进制整数部分 111 转换为二进制,用除 2 取余的方法可得 1101111。将十进制小数部分 0.111 转换为二进制,采用乘 2 取整的方法,0.111×2 = 0.22,整数部分为 0;0.22×2 = 0.44,整数部分为 0;0.44×2 = 0.88,整数部分为 0;0.88×2 = 1.76,整数部分为 1;0.76×2 = 1.52,整数部分为 1;0.52×2 = 1.04,整数部分为 1 等,得到小数部分二进制是 0001110001 ,合起来就是 1101111.0001110001。
- 答案:B
- 解析:在 C++ 中,补码的主要作用是简化整数的加减法运算。通过补码,减法可以转换为加法进行计算,提高运算效率。补码并不能提高浮点数的精度,浮点数精度由其存储格式决定;也不能增加整数的表示范围,8 位有符号整数补码表示范围是固定的;与内存分配也没有直接关系。
- 答案:A
- 解析:8 位有符号整数(使用补码表示),最高位为符号位,剩下 7 位表示数值。正数范围是 0 到 01111111(即 127),负数范围是 10000000 到 11111111,其中 10000000 表示 -128,所以范围是 -128 到 127。
- 答案:C
- 解析:将有符号整数 a = -5 赋值给无符号整数 b 时,会进行类型转换。 -5 在内存中的二进制表示(补码)是 11111011,将其作为无符号整数看待,其值为 4294967291(按无符号整数解析二进制数),所以输出 4294967291 。不是编译错误,也不是 -5 或 5。
- 答案:A
- 解析:在 C++ 中,cout << oct << decimal; 语句中 oct 是八进制操纵符,它将后面输出的十进制数 decimal 按照八进制的格式输出,所以作用是将十进制数转换成八进制数。
- 答案:C
- 解析:在 C++ 中,hex 是十六进制操纵符,cout << hex << decimal; 语句可以将十进制数 decimal 按照十六进制的格式输出,从而实现十进制转十六进制。A 选项 oct 是八进制操纵符;B 选项写法错误,不能实现转换;D 选项可以正确执行。
- 答案:D
- 解析:代码中 a 和 b 都是二进制表示的整数,“^” 在 C++ 中是按位异或运算符,所以代码进行的是按位异或运算。不是整体异或运算(整体异或在 C++ 中没有这种简单运算符),也不是按位同或运算(同或运算符是 “⊙”,C++ 中没有直接的同或运算符 ),更不是按位与运算(按位与运算符是 “&” )。
- 答案:D
- 解析:枚举法查找最大值索引的逻辑是遍历数组,比较当前元素和已记录的最大值元素。如果当前元素大于已记录的最大值元素,就更新最大值索引。所以应该是 if (arr [i] > arr [maxIndex]) 。A 选项判断条件错误,比较反了;B 选项 arr [i] - 1 > arr [maxIndex] 不符合查找最大值的逻辑;C 选项 arr [i] + 1 > arr [maxIndex] 也不符合查找逻辑。
- 答案:D
- 解析:程序的目的是将数组中的奇数和偶数分别放在数组的前半部分和后半部分。当找到左边的偶数(arr [left] % 2 == 0 )时,需要在右边找到奇数(arr [right] % 2 != 0 ),然后交换它们的位置。所以应该是 while (arr [right] % 2 == 0 && left < right) right--; 。A 选项 while (arr [left] % 2 == 0 && left < right) right--; 会导致在左边找偶数,不符合逻辑;B 选项 left-- 错误,应该是 right 移动;C 选项 while (arr [right] % 2 != 0 && left < right) right--; 会导致在右边找偶数,不符合要求。
- 答案:B
- 解析:str.replace (5, 5, "C++"); 表示从字符串 str 的第 5 个位置开始(索引从 0 开始),替换 5 个字符为 “C++”,原字符串 “HelloWorld” 中从第 5 个位置开始的 5 个字符是 “World”,替换后得到 “HelloC++”。A 选项 str.replace (0, 5, "C++"); 会将 “Hello” 替换为 “C++”,得到 “C++World”;C 选项 str.replace (1, 5, "C++"); 会从第 1 个位置开始替换,得到 “C++loWorld”;D 选项 str.replace (4, 5, "C++"); 会从第 4 个位置开始替换,得到 “HelloC++ld”。
- 答案:A
- 解析:str.substr (5, 5); 表示从字符串 str 的第 5 个位置开始(索引从 0 开始),截取长度为 5 的子串。原字符串 “HelloC++” 从第 5 个位置开始的 5 个字符是 “world”。B 选项 str.insert (4, "World"); cout << str.substr (4, 4); 插入 “World” 后,截取的 4 个字符不是 “world”;C 选项 str.insert ("World"); 插入方式错误;D 选项 str.insert (5, "World"); 插入后截取的子串也不是 “world”。
- 答案:C
- 解析:题目要求美丽数字是 9 的倍数但不是 8 的倍数,所以判断条件应该是 if (a % 9 == 0 && a % 8 != 0) 。A 选项 if (a % 9 != 0 && a % 8 != 0) 判断的是既不是 9 的倍数也不是 8 的倍数的数;B 选项 if (a % 9 == 0 & a % 8 == 0) 中 “&” 是按位与运算符,不是逻辑与运算符,且判断的是既是 9 的倍数又是 8 的倍数的数;D 选项 if (a % 9 == 0 & a % 8 != 0) 同样 “&” 使用错误。
二、判断题
- 答案:错误
- 解析:判断一个三角形是否成立,不仅需要任意两边长度之和大于第三条边的长度,还需要任意两边长度之差小于第三条边的长度。只考虑前者不全面。
- 答案:错误
- 解析:代码中 cout <<(x & 1? "YES" : "NO") << '\n'; 判断的是字符 x 的 ASCII 码值的最低位(即最后一位二进制数)是否为 1,而不是判断 ASCII 码是否为奇数。判断 ASCII 码是否为奇数应该用 (x % 2 == 1) 。
- 答案:正确
- 解析:程序中 cout<<((n%4==0&&n%100!=0)||(n%400==0))?1:0; 根据闰年的定义,普通闰年是年份能被 4 整除且不是 100 的倍数,世纪闰年是年份能被 400 整除,该判断逻辑正确。
- 答案:正确
- 解析:n % 15 == 0 表示 n 能被 15 整除,因为 15 = 3×5,所以能被 15 整除的数一定能被 3 和 5 同时整除。
- 答案:正确
- 解析:从 n 个同学中抽取任意个人数参加大合唱,每个人都有参加和不参加两种情况,根据排列组合的乘法原理,总的方法数就是 2×2×...×2(n 个 2 相乘),即 2 的 n 次幂。
- 答案:错误
- 解析:将 2025 转换为二进制:2025÷2 = 1012 余 1,1012÷2 = 506 余 0,506÷2 = 253 余 0,253÷2 = 126 余 1,126÷2 = 63 余 0,63÷2 = 31 余 1,31÷2 = 15 余 1,15÷2 = 7 余 1,7÷2 = 3 余 1,3÷2 = 1 余 1,1÷2 = 0 余 1,得到 111111000001,其中 1 的个数为 8,是偶数个,所以 2025 化为二进制后是 A 类数,但题目表述 “2025 为 A 类数” 错误,应该说 2025 化为二进制后的数是 A 类数。
- 答案:正确
- 解析:while (n != 0) 循环中,cout << n/2 << ' ' << n%2 << '\n'; 输出 n 除以 2 的商和余数,然后 n /= 2; 更新 n 的值,直到 n 为 0,符合题目描述。
- 答案:错误
- 解析:13 进制数 A(十进制下为 10)和 B(十进制下为 11)相加,10 + 11 = 21,将 21 转换为 13 进制,21÷13 = 1 余 8,所以 (A + B)₁₃ = (18)₁₃是错误的,正确结果应该是 (18)₁₀转换为 13 进制,即 (15)₁₃ 。
- 答案:正确
- 解析:在 k 进制中,逢 k 进一位,所以是 k 进第二位,k² 进百位,k³ 进千位,这是 k 进制的进位规则。
- 答案:错误
- 解析:将 CCF(十九进制)转换为十进制:C 在十进制中是 12,F 是 15,CCF = 12×19² + 12×19¹ + 15×19⁰ = 12×361 + 12×19 + 15 = 4332 + 228 + 15 = 4575 。将 21AC(十三进制)转换为十进制:2×13³ + 1×13² + 10×13¹ + 12×13⁰ = 2×2197 + 1×169 + 10×13 + 12 = 4394 + 169 + 130 + 12 = 4705 。两者不相等。
GESP四级
一、单选题
- 答案:A
- 解析:在 C++ 中,函数声明可以放在函数使用之前,函数定义可以放在函数使用之后,所以函数 multiply 的定义不一定要放到函数 main 之前,A 选项错误。函数声明 int multiply (int x, int y); 明确指定了返回值为整数类型,B 选项正确。在 main 函数中,通过 multiply (a, b) 调用函数,a 和 b 作为实参传递给 multiply 函数的形参 x 和 y,C 选项正确。运行代码,4 乘以 5 结果为 20,会输出 The result is: 20,D 选项正确。
- 答案:B
- 解析:在 func 函数中,定义了局部变量 x,其作用域仅限于 func 函数内部,值为 20,所以 func 函数输出 20。在 main 函数中,变量 x 是在 main 函数中定义的,值为 10,所以 main 函数输出 10,最终输出 2010,B 选项正确。
- 答案:B
- 解析:int* p = &a; 语句使指针 p 指向变量 a,*p = 20; 语句通过指针 p 修改了 a 的值,所以变量 a 的值变为 20,B 选项正确。
- 答案:D
- 解析:引用传递和指针传递都不会拷贝大型对象,它们传递的是对象的引用或地址,避免了对象的拷贝,提高了效率,D 选项正确。值传递会拷贝对象,对于大型对象会消耗较多资源,A 选项错误。引用传递和指针传递都能避免拷贝大型对象,B、C 选项表述不全面。
- 答案:D
- 解析:在 swap 函数中,形参 a 是值传递,对形参 a 的修改不会影响实参 x。形参 b 是引用传递,能修改实参 y 的值。但函数中交换逻辑错误,正确交换代码应该是
temp = a; a = b; b = temp;
,而原代码执行后 a 和 b 的值相同且都为原来 b 的值,所以 x 的值不变,y 的值变为原来 x 的值,输出 11,D 选项正确。
- 解析:在 swap 函数中,形参 a 是值传递,对形参 a 的修改不会影响实参 x。形参 b 是引用传递,能修改实参 y 的值。但函数中交换逻辑错误,正确交换代码应该是
- 答案:C
- 解析:A 选项中,结构体 Person 的变量 p 初始化语法错误,应该使用大括号初始化列表。B 选项中,先定义了 Person 结构体变量 p,然后分别赋值,这种方式没有在定义时初始化。C 选项使用大括号初始化列表正确初始化了 Person 结构体变量 p,C 选项正确。D 选项中,使用 new 关键字是在堆上创建对象,返回的是指针,而 p 是 Person 类型变量,不是指针,语法错误。
- 答案:D
- 解析:从代码可知,结构 Person 内嵌套了结构 Address,A 选项正确。Person 有一个 Address 类型的成员 address,B 选项正确。可以通过 p.address.street 和 p.address.city 的方式对 Person 类型变量 p 的 address 成员进行初始化,C 选项正确。结构的嵌套虽然可以减少命名冲突,但嵌套层次过深会使代码结构复杂,可读性降低,所以需要控制嵌套层次,D 选项错误。
- 答案:D
- 解析:对于二维数组 int arr [2][3] = {{1,2,3},{4,5,6}}; ,arr [1][2] 表示第二行(从 0 开始计数)第三列的元素,其值为 6,D 选项正确。
- 答案:B
- 解析:在 C++ 中,二维数组的正确定义方式是 int arr [3][4]; ,方括号表示数组维度,B 选项正确。A 选项 int arr [3,4]; 中使用逗号不符合语法规则。C 选项 int arr (3,4); 括号的使用错误。D 选项 int a [3 - 4]; 中数组维度不能是负数或表达式结果为负数。
- 答案:B
- 解析:该递推算法用于计算爬楼梯的不同方法数。f1 表示爬到第 i - 2 级台阶的方法数,f2 表示爬到第 i - 1 级台阶的方法数,爬到第 i 级台阶的方法数 res 等于爬到第 i - 1 级和第 i - 2 级台阶方法数之和,即 res = f1 + f2。然后更新 f1 和 f2,将 f2 的值赋给 f1,将 res 的值赋给 f2,B 选项正确。A 选项中 res += f1 + f2; 会导致结果错误,每次循环不是简单累加。C 和 D 选项中 f1 和 f2 的更新顺序错误。
- 答案:时间复杂度为\(O(2^n \times n)\)(题目中未给出选项内容,推测题目是考查该算法时间复杂度分析)
- 解析:外层循环
for (int i = 0; i < (1 << n); i++)
,其中1 << n
表示\(2^n\),所以外层循环执行\(2^n\)次。内层循环for (int j = 0; j < n; j++)
,每次外层循环时,内层循环都执行 n 次。所以总的时间复杂度为\(O(2^n \times n)\) 。
- 解析:外层循环
- 答案:B
- 解析:排序的稳定性是指稳定排序保证相同元素的相对顺序不变,B 选项正确。稳定性与算法的时间复杂度无关,A 选项错误。选择排序不是稳定排序,在选择排序过程中,相同元素的相对顺序可能会改变,C 选项错误。插入排序是稳定排序,在插入过程中,相同元素不会交换顺序,D 选项错误。
- 答案:A
- 解析:冒泡排序是相邻元素两两比较,将较大的元素向后移动。对于数组 arr [] = {5, 3, 8, 1} 进行升序排序,第一轮冒泡排序会比较相邻元素并交换,5 和 3 比较交换,3 和 8 比较不交换,8 和 1 比较交换,得到 3, 5, 1, 8,A 选项正确。
- 答案:A
- 解析:在 hmean 函数中,当 a == -b 时,抛出 runtime_error 异常。在 main 函数的 try - catch 块中,捕获到该异常并输出 Caught: Runtime error occurred.,A 选项正确。不会输出 Caught an unknown exception.,B 选项错误。程序不会调用 std::terminate (),C 选项错误。代码没有编译错误,D 选项错误。
- 答案:C
- 解析:A 选项使用 freopen 函数将标准输出重定向到文件 log.txt,然后输出字符串,最后关闭文件,能实现重定向。B 选项使用 std::ofstream 创建文件流对象 outFile,向文件中输出字符串后关闭文件,可实现重定向。C 选项中,std::ofstream 创建文件流对象后,cout 输出字符串时,cout 是标准输出,不会自动重定向到文件,不能实现重定向,C 选项错误。D 选项通过修改 cout 的缓冲区指针,将输出重定向到文件 log.txt,最后恢复原缓冲区指针,能实现重定向。
二、判断题
- 答案:正确
- 解析:函数是 C++ 中重要概念,它将一段可重用的代码封装起来,提高代码的模块化和复用性。
- 答案:错误
- 解析:在 C++ 中,函数的返回类型不能省略,若省略返回类型,编译器会报错,不会默认返回 int 。
- 答案:正确
- 解析:结构体的成员默认访问权限是 public,而类的成员默认访问权限是 private。
- 答案:错误
- 解析:指针 p 指向数组 arr 的首元素,p += 1; 后,指针 p 会指向下一个元素,其值是数组首元素地址加上一个元素的大小(假设 int 类型占 4 字节,地址会增加 4),而不是值为 1。
- 答案:错误
- 解析:二维数组作为函数参数时,第一维的大小可以省略,但第二维的大小必须显式指定,因为在函数内部需要知道数组每行的元素个数来正确访问数组元素。
- 答案:正确
- 解析:递推算法就是通过已知的初始值和递推公式,逐步计算出目标值。例如斐波那契数列,通过已知的前两项,利用递推公式计算后续项。
- 答案:错误
- 解析:冒泡排序在最坏情况下,每一轮都要比较 n - 1 次,总共 n - 1 轮,时间复杂度递推关系式为\(T(n) = T(n - 1)+ (n - 1)\),\(T(1)=0\) ,而不是\(T(n)=T(n - 1)+n\) ,\(T(0)=1\) 。
- 答案:错误
- 解析:插入排序在最好情况(已有序)下,只需要比较 n - 1 次,时间复杂度是\(O(n)\) ,而不是\(O(n^2)\) 。
- 答案:正确
- 解析:选择排序是从未排序元素中选择最小(或最大)元素,放到已排序序列的末尾。对数组 arr [] = {4, 3, 1, 5, 2} 进行升序排序,第一轮选择排序会找到最小元素 1,与第一个元素 4 交换,得到 {1, 4, 3, 5, 2} 。
- 答案:正确
- 解析:在 C++ 中,如果程序中有未捕获的异常,会调用 std::terminate 终止程序,防止程序出现未定义行为。
GESP五级
一、单选题
- 答案:A
- 解析:链表的特点是插入、删除操作不需要移动元素,只需修改指针,B 选项正确;无需事先估计存储空间大小,所需存储空间与存储元素个数成正比,C、D 选项正确。但链表不能随机访问任何一个元素,只能顺序访问,A 选项错误。
- 答案:A
- 解析:删除双向链表中结点 p 时,需要修改 p 的前驱和后继结点的指针,使其绕过 p。B 选项中,先将 p 的前驱结点的 next 指针指向 p 的后继结点,再将 p 的后继结点的 prev 指针指向 p 的前驱结点,最后删除 p,操作正确;C 选项先将 p 的后继结点的 prev 指针指向 p 的前驱结点,再将 p 的前驱结点的 next 指针指向 p 的后继结点,最后删除 p,操作正确;D 选项同理,操作正确。A 选项中,p->next->prev = p->next; 这一步会使 p 的后继结点的 prev 指针指向自身,导致链表结构错误,A 选项错误。
- 答案:B
- 解析:对于双向循环链表,头结点的 next 指针应指向尾结点,尾结点的 prev 指针应指向头结点。A 选项中 list->head->prev = list->head; 会使头结点的 prev 指针指向自身,不符合双向循环链表结构;C 选项中 list->tail->next = list->head; 虽然使尾结点的 next 指针指向头结点,但没有正确设置尾结点的 prev 指针;D 选项中 list->tail->next = nullptr; 不符合循环链表的结构。B 选项正确设置了头结点的 next 指针和尾结点的 prev 指针,B 选项正确。
- 答案:B
- 解析:辗转相除法求 gcd (84, 60),第一步:big = 84,small = 60,84 % 60 = 24;第二步:此时 big = 60,small = 24,B 选项正确。
- 答案:D
- 解析:唯一分解定理要求分解出的因数都是质数。A 选项中 6 不是质数;B 选项中 4 不是质数;C 选项中 6 不是质数;D 选项 30 = 2×3×5,2、3、5 都是质数,分解正确,D 选项正确。
- 答案:C
- 解析:线性筛法的内层循环需要在质数数组范围内,并且确保 i * primes [j] 不超过 n。A 选项只考虑了 j 在质数数组范围内,没有限制 i * primes [j] 的大小;B 选项没有限制 j 在质数数组范围内;D 选项 j <= n 不符合线性筛法的逻辑。C 选项同时满足在质数数组范围内且 i * primes [j] <= n 的条件,C 选项正确。
- 答案:A
- 解析:递归调用过程中,函数调用信息会存储在栈中,如果递归层数过多,会导致系统分配的栈空间溢出,A 选项正确。堆空间主要用于动态内存分配,与递归调用层数过多引发的错误无关,B 选项错误;队列和链表空间也与递归调用层数过多导致的错误没有直接关系,C、D 选项错误。
- 答案:D
- 解析:factorialA 和 factorialB 都用于计算 n 的阶乘,功能相同,A 选项正确;两个函数时间复杂度均为\(O(n)\) ,B 选项正确;factorialA 采用递归方式,C 选项正确;factorialB 采用循环方式,不是递归方式,D 选项错误。
- 答案:A
- 解析:选择排序在选择最小(或最大)元素时,会与未排序部分的元素交换位置,可能会改变相同元素的相对顺序,是不稳定排序,A 选项正确。插入排序、归并排序、冒泡排序在排序过程中,相同元素不会交换顺序,是稳定排序,B、C、D 选项错误。
- 答案:B
- 解析:快速排序的 partition 函数中,需要将小于基准值的元素放到基准值左边。A 选项中判断条件 arr [j] > pivot 会将大于基准值的元素放到左边,不符合快速排序逻辑;C 选项中 swap (arr [i], arr [j]); 和 i++; 顺序错误,会导致交换的元素位置不正确;D 选项判断条件 arr [j] == pivot 不符合快速排序分区逻辑。B 选项判断 arr [j] < pivot,将小于基准值的元素交换到左边,同时正确更新 i 的值,B 选项正确。
- 答案:C
- 解析:二分法每次将搜索区间缩小一半,对于区间 [1, 100],\(2^6 = 64\),\(2^7 = 128\),最多需要猜 7 次就能确定目标值,C 选项正确。
- 答案:A
- 解析:二分查找中计算中间位置 mid 的公式为 mid = left + (right - left) / 2,这样可以避免 left + right 可能产生的溢出问题。B 选项 mid = left 会导致每次都从左端点开始查找;C 选项 (left + right) / 2 在 left + right 较大时可能会溢出;D 选项 mid = right 会导致每次都从右端点开始查找。A 选项正确。
- 答案:A
- 解析:贪心算法的核心特征是总是选择当前最优解,A 选项正确。回溯算法是尝试所有可能;分治算法是分阶段解决子问题;贪心算法不一定总能找到最优解,B、C、D 选项错误。
- 答案:D
- 解析:分治逻辑是将问题分解为子问题,分别求解子问题,再合并结果。A 选项中直接返回 arr [mid] 没有正确合并子问题结果;B 选项中 leftMax + rightMax 不是求最大值的正确方式;C 选项中 leftMax * rightMax 也不是求最大值的正确方式。D 选项中当 low == high 时返回 arr [low],然后通过递归分别求左右子数组的最大值,最后返回较大值,正确实现了分治逻辑,D 选项正确。
- 答案:B
- 解析:在高精度乘法处理进位时,需要将当前位的值与进位值相加,然后取个位作为当前位的值,十位作为新的进位值。A 选项只考虑当前位的值,没有加上进位;C 选项 c [k] - carry 不符合进位处理逻辑;D 选项 c [k] * carry 也不符合进位处理逻辑。B 选项 int temp = c [k] + carry; 正确处理了进位,B 选项正确。
二、判断题
- 答案:正确
- 解析:在单链表中删除非尾结点 p 且不知道头结点时,可以将 p->next 的值赋给 p,然后删除 p->next,这样既删除了 p 所指向的逻辑结点,又保持了链表的连续性。
- 答案:错误
- 解析:链表存储线性表时,内存中可用存储单元地址不一定连续,它通过指针来连接各个结点,与数组要求内存地址连续不同。
- 答案:正确
- 解析:线性筛法通过记录每个合数的最小质因数,使得每个合数只会被它的最小质因数筛去一次,相比埃拉托斯特尼筛法,减少了重复筛除合数的操作,效率更高。
- 答案:错误
- 解析:贪心算法虽然每一步选择当前最优解,但这并不一定能保证获得全局最优解。例如在 0 - 1 背包问题中,贪心算法可能无法得到最优解。只有在满足特定条件(如最优子结构和贪心选择性质)时,贪心算法才能得到全局最优解。
- 答案:正确
- 解析:递归函数如果没有终止条件,会一直递归调用下去,导致栈溢出,所以必须有一个终止条件来结束递归。
- 答案:错误
- 解析:快速排序算法在平均情况下时间复杂度为\(O(n log n)\) ,但在最坏情况下(如输入数组已经有序),时间复杂度为\(O(n^2)\) 。
- 答案:正确
- 解析:归并排序每次将数组分成大致相等的两部分,然后对这两部分分别排序,最后合并。无论输入数组是否有序,其时间复杂度始终为\(O(n log n)\) 。
- 答案:错误
- 解析:二分查找要求数组是有序的,因为二分查找利用了数组的有序性,通过比较中间元素和目标元素来缩小查找范围。对于无序数组,无法使用二分查找。
- 答案:错误
- 解析:小杨每次挑价格最低的商品买,这体现的是贪心思想,而不是分治思想。贪心算法是在每一步选择当前最优解,分治算法是将问题分解为子问题分别求解。
- 答案:正确
- 解析:归并排序将大的待排序数组分成大小大致相等的两个小数组,对这两个小数组分别排序,最后将排好序的两个小数组合并成有序数组,体现了分治算法的思想。
GESP六级
一、单选题
- 答案:D
- 解析:类定义后,其属性和方法可以通过继承、扩展等方式进行修改。例如在 C++ 中,派生类可以继承基类的属性和方法,并根据需求进行重写或添加新的属性和方法,A、B、C 选项对类的描述均正确。
- 答案:B
- 解析:在构造哈夫曼树时,频率越低的字符离根节点越远,频率越高的字符离根节点越近,A、C、D 选项对哈夫曼编码的描述正确。
- 答案:A
- 解析:代码中先访问根节点,再递归访问左子树,最后递归访问右子树,符合前序遍历的顺序。中序遍历是先左子树,再根节点,最后右子树;后序遍历是先左子树,再右子树,最后根节点;层次遍历是按层访问节点 。
- 答案:B
- 解析:代码通过队列按层遍历二叉树,在遍历过程中检查节点是否为空以及空节点出现的位置,以此判断树是否为完全二叉树。满二叉树要求每个节点都有两个子节点(除了叶子节点);二叉搜索树要求左子树节点值小于根节点值,右子树节点值大于根节点值;代码中未涉及树高度的计算。
- 答案:B
- 解析:代码中根据插入值与当前节点值的大小关系,递归地将新节点插入到合适的位置(左子树或右子树),实现的是二叉排序树的插入操作。查找操作是判断树中是否存在某个值;删除操作需要考虑多种情况,如删除节点为叶子节点、只有一个子节点或有两个子节点等;遍历操作是按一定顺序访问树中的所有节点。
- 答案:B
- 解析:根据哈夫曼编码的规则,频率高的字符编码短,频率低的字符编码长。字符集 {A, B, C, D} 频率 {5, 1, 6, 2},C 频率最高编码应为最短的 “0”,B 频率最低编码应最长,“100” 符合,A 为 “11” ,D 为 “101” 。
- 答案:B
- 解析:动态规划要求问题具有最优子结构和重叠子问题性质,这样才能通过保存中间结果避免重复计算。动态规划算法时间复杂度不一定低于贪心算法,取决于具体问题;动态规划通过递归实现时通常需要存储中间结果,以避免重复计算;其核心思想是将问题分解为重叠子问题。
- 答案:B
- 解析:MyClass obj1; 语句调用了一次构造函数,创建 obj1 对象。MyClass obj2 = obj1; 语句在创建 obj2 对象时,调用的是拷贝构造函数(若未自定义拷贝构造函数,编译器会生成默认的),而非构造函数,所以构造函数共调用 2 次。
- 答案:A
- 解析:enQueue 函数中,先检查队列是否已满,若未满则将元素添加到队列尾部(通过调整 rear 指针并赋值),实现了循环队列的入队操作。出队操作是移除队首元素;查看队首元素是获取队首元素的值;判断队列是否为空有专门的 isEmpty 函数判断。
- 答案:A
- 解析:深度优先搜索(DFS)通过栈实现,在处理完当前节点后,应将其左子节点(若存在)入栈,继续对左子树进行深度优先搜索。B 选项 s.pop (node->left) 是弹出操作,不符合 DFS 逻辑;C 选项 s.front (node->left) 中 front 函数一般用于获取队首元素,栈没有该操作;D 选项将右子节点再次入栈,不符合正常 DFS 遍历顺序。
- 答案:A
- 解析:广度优先搜索(BFS)通过队列实现,在处理当前节点时,应将其左子节点和右子节点(若存在)依次加入队列,以便后续按层遍历。B 选项 pop 操作是移除元素,不是加入;C 选项 front 操作是获取队首元素,不是加入;D 选项加入节点的顺序错误,应先左后右。
- 答案:A
- 解析:生成格雷编码时,在已有 n - 1 位格雷编码基础上,通过在前缀添加 “0” 和 “1” 生成 n 位格雷编码。后半部分循环是从前缀添加 “1”,所以应是 result.push_back ("1" + prev [i])。B 选项添加 “0” 与前半部分重复;C、D 选项是在编码后添加字符,不符合格雷编码生成规则。
- 答案:B
- 解析:在 0/1 背包问题动态规划解法中,当当前物品重量 weights [i - 1] 小于等于背包剩余容量 j 时,需要在不放入当前物品(dp [i - 1][j])和放入当前物品(dp [i - 1][j - weights [i - 1]] + values [i - 1])两种情况中选择价值最大的。A 选项未考虑放入物品的情况;C 选项比较对象错误;D 选项计算顺序错误。
- 答案:C
- 解析:检查括号匹配时,遍历完字符串后,若栈为空,说明所有左括号都有对应的右括号匹配,返回 true;若栈不为空,说明有左括号未匹配,返回 false。A 选项直接返回 true 无法判断栈中是否还有未匹配括号;B 选项直接返回 false 不符合逻辑;D 选项!st.empty () 表示栈不为空,与正确逻辑相反。
- 答案:A
- 解析:Shape* shapePtr = &circle; 和 shapePtr = &rectangle; 语句不会出现编译错误,这是多态的体现,通过基类指针可以指向派生类对象,调用派生类重写的虚函数。B 选项,Shape 是基类,Circle 和 Rectangle 是派生类;C 选项,派生类复用了基类的属性和方法并扩展功能;D 选项,Circle 和 Rectangle 重写 area 函数,通过基类指针实现运行时多态 。
二、判断题
- 答案:正确
- 解析:哈夫曼树构造过程中,每次合并权值最小的两个节点,这样生成的树带权路径长度最小,这是哈夫曼树的特性。
- 答案:错误
- 解析:格雷编码相邻两个编码之间只有一位不同,这样可以减少数据传输错误。若有多位不同,在数据传输过程中更容易出错。
- 答案:错误
- 解析:树的深度优先搜索(DFS)使用栈作为辅助数据结构,实现 “先进后出” 的访问顺序;广度优先搜索(BFS)使用队列作为辅助数据结构,实现 “先进先出” 的访问顺序。
- 答案:正确
- 解析:代码中先递归遍历左子树,再输出根节点值,最后递归遍历右子树,符合二叉树中序遍历的顺序。
- 答案:正确
- 解析:C++ 支持构造函数重载,可以有多个不同参数列表的构造函数,但默认无参数的构造函数只能有一个。若有多个无参构造函数,在创建对象时会产生歧义 。
- 答案:错误
- 解析:二叉排序树(BST)中,若某节点左子树为空,其右子树所有节点值都大于该节点值,但该节点不一定是树中的最小值节点。树中的最小值节点是从根节点一直向左走到尽头的节点。
- 答案:正确
- 解析:用动态规划解决硬币找零问题,硬币面额 [1, 3, 4],目标金额 6。可以用 2 枚面额为 3 的硬币(3 + 3)凑成 6,这是最少硬币数量的组合。
- 答案:正确
- 解析:面向对象编程中,封装将数据和操作数据的方法绑定在一起,通过访问控制符(如 private、protected、public)对外隐藏实现细节,提高安全性和可维护性。
- 答案:错误
- 解析:完全二叉树除了最后一层外,每一层的节点数都是满的,且最后一层的节点都集中在左边。代码中创建的树,根节点的右子树有节点 3,但其左子树的右子节点为空,不符合完全二叉树定义。
- 答案:正确
- 解析:栈和队列都可以用双向链表实现。在双向链表中,插入和删除操作只需修改指针,时间复杂度为 O (1)。栈操作如入栈、出栈,队列操作如入队、出队,都能高效实现。
因为我太弱了,7和8觉得太难,写不了,等我水平强大了再来写……