四级只会背模板?
指针到排序一条线
11 套真题讲透
指针 · 二维数组 · 结构体 · 函数 · 递推 · 排序 · 文件 · 异常
DOMIAI · GESP 复习
📦 7 Parts
👉 左右滑动
PART 01
大纲总览
8 大块
PART 02
知识点
指针到异常
PART 03
真题分析
11 套
PART ///
写在最后
冲刺计划
适用考试:CCF 编程能力等级认证(GESP)C++ 四级
考试时间:120分钟 | 满分:100分
题型:单选题15题(30分,每题2分)+ 判断题10题(20分,每题2分)+ 编程题2题(50分,每题25分)
资料基于 官方四级大纲(C++部分) 和 2023年6月~2026年6月共11套真题 整理
说明:本资料仅覆盖C++相关知识点,不涉及Python内容。
指针和排序,是四级拉开分差的关键
01
PART
考试大纲总览
OUTLINE · 大纲
一、考核目标(C++)
掌握 C++指针类型、二维及多维数组(不包括变长数组)的基本使用。通过函数相关知识的学习,掌握模块化设计思想,具备编写自定义函数程序的能力。掌握文件读写操作,并通过对排序算法、递推法的学习,可以根据不同的使用场景,合理选择最优的算法。
四级比三级多了什么?——八大新知识点
指针——C++的灵魂,可以直接操作内存地址
结构体——自定义数据类型,把多个数据打包在一起
二维及多维数组——从“一排”到“一个平面”甚至“一个立方体”
函数进阶——作用域、三种参数传递方式(值传递、引用传递、指针传递)
递推算法——用已知推未知,经典算法思想
排序算法——冒泡、插入、选择,编程的“基本功”
文件操作——让程序能读写磁盘上的文件
异常处理——让程序在出错时能优雅处理
二、考试内容——8大知识块(C++部分)
根据官方四级大纲(共11条知识点,以下仅列出C++相关部分),C++四级考试共考核 8个知识块:
①
知识块:指针(C++特有)
大纲对应条号:第1条
核心知识点:指针类型定义、赋值、解引用、指针运算
难度:★★★★
考试占比:约20%
②
知识块:二维及多维数组
大纲对应条号:第2条(C++部分)
核心知识点:定义、使用、内存布局、遍历、作为函数参数
难度:★★★
考试占比:约12%
③
知识块:结构体(C++特有)
大纲对应条号:第2条(C++部分)
核心知识点:定义、使用、结构体数组/指针/嵌套、const
难度:★★★
考试占比:约10%
④
知识块:函数
大纲对应条号:第3、4、5条(C++部分)
核心知识点:声明/定义/调用、形参/实参、作用域、三种参数传递方式
难度:★★★
考试占比:约15%
⑤
知识块:递推算法
大纲对应条号:第6条
核心知识点:递推思想、递推关系式推导、递推问题求解
难度:★★★
考试占比:约8%
⑥
知识块:排序算法
大纲对应条号:第7、8条
核心知识点:冒泡排序、插入排序、选择排序;内排序/外排序;稳定性
难度:★★★★
考试占比:约15%
⑦
知识块:文件操作
大纲对应条号:第10条
核心知识点:文件重定向、读/写/读写操作
难度:★★
考试占比:约10%
⑧
知识块:异常处理
大纲对应条号:第11条
核心知识点:try-catch-throw 机制
难度:★★
考试占比:约5%
难度最高的知识点:指针和排序算法(概念抽象且容易出错)
出现频率最高的知识点:指针、二维数组、函数参数传递(几乎每套题都有)
02
PART
各知识点详解
KNOWLEDGE · 知识点
知识块①:指针——“C++的灵魂”
·1.1 什么是指针?——“门牌号”比喻
指针就是存放内存地址的变量。 就像你家的门牌号——门牌号本身不是房子,但通过门牌号可以找到房子。
int a = 10; // 普通变量,存的是数值 10
int *p = &a; // 指针变量 p,存的是 a 的地址
在内存中:
变量 a: [10] 地址: 0x6ffe14
指针 p: [0x6ffe14] 地址: 0x6ffe18(p 存的是 a 的地址)
·1.2 指针的核心操作:定义、取地址、解引用
定义指针:int *p; — 定义一个指向 int 类型的指针
取地址:&a — 获取变量 a 的地址
解引用:*p — 通过指针 p 访问它指向的变量
int a = 10;
int *p = &a; // p 指向 a
cout << p; // 输出 a 的地址,如 0x6ffe14
cout << *p; // 输出 10(通过 p 访问 a 的值)
*p = 20; // 等价于 a = 20,通过指针修改 a 的值
cout << a; // 输出 20
练习题:指针变量 p 的值和变量 n 的值有什么关系?
int n = 10;
int *p = &n;
解析: p 的值是 n 的地址;*p 的值是 n 的值(10)。p 和 n 本身的值不同。(2023年9月第9题)
指针变量本身的类型:int *p 中,p 的类型是 int *(指向 int 的指针),而不是 int。(2023年6月第8题)
·1.3 指针运算——最重要!p++ 跳几个字节?
指针也可以做加减法,但加减的不是普通数字,而是类型的大小。
int arr[3] = {1, 2, 3};
int *p = arr; // p 指向 arr[0],地址假设为 0x1000
p++; // p 指向 arr[1],地址变为 0x1004(int 占4字节)
cout << *p; // 输出 2(arr[1] 的值)
(2023年12月第5题、第6题)
练习题: 如果 x 的地址是 0x6ffe14,int *p = &x; p++; 后 p 的地址是?
解析: int 占4字节,p++ 后地址增加4,变为 0x6ffe18。(2023年12月第6题)
·1.4 指针和数组
数组名就是数组首元素的地址。
int a[5] = {1, 2, 3, 4, 5};
int *p = &a[2]; // p 指向 a[2](值为3)
a[1] = *p; // 把 a[2] 的值赋值给 a[1],a[1] 变成3
// a 变为 {1, 3, 3, 4, 5}
(2023年6月第11题)
练习题:
int a[5] = {1, 2, 3, 4, 5};
int *p = &a[2];
*p = a[1]; // *p 就是 a[2],a[2] 被赋值为 a[1] 的值2
// a 变为 {1, 2, 2, 4, 5}
(2023年9月第12题)
练习题:指针 + 字符串输出
char *p = "I love GESP!";
cout << p + 5 << endl; // p 指向 'I',p+5 指向第5个字符(从0开始)
// 输出从第5个字符开始:"e GESP!"
(2024年3月第6题)
·1.5 空指针 nullptr
int *p = nullptr; // p 不指向任何有效地址
// 访问 *p 会导致运行时错误(段错误),但不会导致编译错误
判断题: “指针变量中存储的是内存地址。” 答案:√。
判断题: “指针变量只能指向基本类型变量,不能指向指针变量。”(2023年6月第3题) 答案:×。可以定义指向指针的指针。
·1.6 指针作为函数参数
void xchg(int *x, int *y) { // 指针传递
int t = *x;
*x = *y;
*y = t;
}
int main() {
int a = 10, b = 20;
xchg(&a, &b); // 传入 a 和 b 的地址
cout << a << " " << b; // 输出 "20 10"
}
(2023年6月第13题)
区分三种传递方式:
void f1(int x) { x = 100; } // 值传递:不改变原值
void f2(int &x) { x = 100; } // 引用传递:改变原值
void f3(int *x) { *x = 100; } // 指针传递:改变原值
·1.7 指针 + sizeof 综合题
int x[] = {2, 0, 2, 4};
char geSP[] = "Grade Examination of SP";
cout << geSP[sizeof(x)] << endl; // sizeof(x) = 4个int × 4字节 = 16
// geSP[16] = 'n'(从0开始数,第16个字符)
(2024年3月第2题)
练习题:指针 + 类型转换
float fnum[10] = {1.1};
fnum[1] = foo(fnum); // foo(float *f) { return int(*f * 2); }
// foo(fnum) 把数组首地址传入,*f = fnum[0] = 1.1
// int(1.1 * 2) = int(2.2) = 2
// fnum[1] = 2, fnum[0] + fnum[1] = 1.1 + 2 = 3.1
(2024年3月第3题)
知识块②:二维及多维数组
·2.1 二维数组——“一个表格”
定义:int a[3][4]; 表示3行4列的二维数组(共12个元素)。
打个比方:二维数组就像一张Excel表格,有行和列。
内存布局: 二维数组在内存中是连续存放的,按行优先顺序存储。(2023年6月第4题)
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
// 内存中:1 2 3 4 5 6 7 8 9(连续存放)
·2.2 二维数组的遍历
倒序输出每一行(2023年12月第4题):
int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
for (int i = 0; i < 3; i++) {
for (int j = 2; j >= 0; j--) {
cout << arr[i][j] << " ";
}
cout << endl;
}
// 输出:3 2 1 / 6 5 4 / 9 8 7
·2.3 二维数组的内存计算
double array[3][10]; // double 占8字节
// 总大小 = 3 × 10 × 8 = 240 字节
(2023年6月第7题)
char array[3][10]; // char 占1字节
// 总大小 = 3 × 10 × 1 = 30 字节
(2023年9月第8题)
·2.4 二维数组在内存中的位置计算
规则:二维数组在内存中是按行优先存储的。
int array[5][3]; // int 占4字节
// array[1][2] 和 array[2][1] 相差多少?
// array[1][2] 是第 1×3+2=5 个元素(从0开始)
// array[2][1] 是第 2×3+1=7 个元素(从0开始)
// 相差 2 个元素,2×4=8 字节
(2023年6月第9题)
·2.5 二维数组作为函数参数
传递二维数组时,必须指定第二维的大小(列数):
void BubbleSort(int a[][4]); // 正确:指定了列数为4
// void BubbleSort(int a[3][]); // 错误:没有指定列数
// void BubbleSort(int a[][]); // 错误:没有指定列数
// void BubbleSort(int **a); // 不是二维数组的正确传参方式
(2023年6月第12题)
·2.6 多维数组
可以定义四维数组, 而且在解决实际问题中有实际用途(如张量运算、图像处理等)。(2023年6月判断第4题)
知识块③:结构体(C++特有)
·3.1 结构体是什么?——“打包多个数据”
结构体就是把多个不同类型的数据打包成一个“复合数据类型”。 就像一张学生信息卡——包含了姓名、年龄、成绩等不同信息。
struct Student {
string name;
int age;
double score;
};
Student s1;
s1.name = "小明";
s1.age = 12;
s1.score = 95.5;
·3.2 结构体数组
Student class[30];
for (int i = 0; i < 30; i++) {
cin >> class[i].name >> class[i].age >> class[i].score;
}
·3.3 结构体指针
Student s1 = {"小明", 12, 95.5};
Student *p = &s1;
cout << p->name; // 用 -> 访问结构体指针的成员
cout << (*p).name; // 等价写法
·3.4 结构体嵌套
struct Address { string city; string street; };
struct Student {
string name;
Address addr; // 嵌套结构体
};
知识块④:函数
·4.1 函数的声明、定义和调用
// 声明
int add(int a, int b);
// 定义
int add(int a, int b) { return a + b; }
// 调用
int result = add(3, 5);
·4.2 形参和实参
形参: 函数定义时写的参数,如 int a, int b
实参: 调用函数时传入的值,如 3, 5
函数调用时必须提供足够的实际参数。(2023年9月第6题)
·4.3 变量作用域——全局变量 vs 局部变量
全局变量: 在所有函数外面定义的变量,整个程序都可以访问
局部变量: 在函数内部定义的变量,只在函数内部有效
int global = 10; // 全局变量
void func() {
int local = 20; // 局部变量
}
注意: 两个函数的局部变量可以重名。(2023年9月第7题)
易错题:
int rc = 5; // 全局变量
int main() {
int rc; // 局部变量,和全局变量重名,局部变量优先
cout << ++rc << endl; // 局部变量rc未初始化,值不确定
}
// 输出:不确定(可能是随机值)
(2024年3月第7题)
·4.4 三种参数传递方式——必考!(C++特有)
值传递(默认): 复制一份,函数内修改不影响原值
void f(int x) { x = 100; }
int a = 10; f(a); cout << a; // 输出 10,没变
引用传递: 传递的是原变量的别名,修改会影响原值
void f(int &x) { x = 100; }
int a = 10; f(a); cout << a; // 输出 100,变了
指针传递: 传递的是地址,通过解引用修改原值
void f(int *x) { *x = 100; }
int a = 10; f(&a); cout << a; // 输出 100,变了
练习题: 若函数声明为 int f(int &x) { x += 3; return x; },对 int a = 3,哪个调用能够改变 a 的值?(2024年3月第1题)
A. f(&a); ← 错误,&a 是指针,不是引用
B. f(*a); ← 错误,语法错误
C. C0 ← 正确,引用传递会改变 a 的值
D. f(a - 3); ← 错误,实参必须是变量
易错判断题: “函数的参数默认以引用传递方式进行传递。”(2023年6月判断第3题) 答案:×。默认是值传递。
判断题: “通过引用传递的参数不会复制实际参数,因此不会额外占用内存。”(2023年9月判断第4题) 答案:√。
判断题: “一个函数没有被调用时,它的参数不占用内存。”(2023年6月判断第5题) 答案:√。
知识块⑤:递推算法
·5.1 什么是递推?
递推就是用已知的“前几项”推出“下一项”。 就像数列——知道前两项,就能推出后面所有的项。
·5.2 经典例子:斐波那契数列
递推关系式:f(n) = f(n-1) + f(n-2),其中 f(1)=1, f(2)=1
int fib[100];
fib[0] = 0; fib[1] = 1;
for (int i = 2; i < 100; i++) {
fib[i] = fib[i-1] + fib[i-2]; // 递推:用前两项推出当前项
}
(2023年6月判断第2题)
·5.3 递推 vs 递归
递推: 从前往后算,用循环实现(2024年3月第8题)
递归: 从后往前分解,用函数调用自身实现
练习题: 下面函数中采用的算法是?(2024年3月第8题)
int fib(int n) {
int i, f[n] = {0, 1};
for (int i = 2; i <= n; i++) f[i] = f[i-1] + f[i-2];
return f[n];
}
答案: A. 递推(没有调用自身)
知识块⑥:排序算法
·6.1 排序的基本概念
内排序: 所有数据在内存中完成排序
外排序: 数据太多,需要借助外部存储
·6.2 稳定性
稳定排序: 两个相等的元素排序前后相对位置不变。(2023年6月第2题)
三种排序的稳定性:
冒泡排序:稳定
插入排序:稳定
选择排序:不稳定
·6.3 冒泡排序
原理: 相邻元素两两比较,大的往后“冒泡”。
void BubbleSort(int array[], int n) {
for (int i = n; i >= 2; i--)
for (int j = 0; j < i - 1; j++)
if (array[j] > array[j + 1]) {
int t = array[j];
array[j] = array[j + 1];
array[j + 1] = t;
}
}
(2023年9月第15题)
时间复杂度: 最好 O(n),最坏 O(n²),平均 O(n²)
空间复杂度: O(1)
·6.4 选择排序
原理: 每次从剩余元素中选出最小的,放到前面。
void SelectionSort(int array[], int n) {
for (int i = 0; i < n - 1; i++) {
int min = i;
for (int j = i + 1; j < n; j++)
if (array[min] > array[j]) // 注意比较的是 array[min] 和 array[j]
min = j;
int temp = array[min];
array[min] = array[i];
array[i] = temp;
}
}
(2023年6月第15题)
时间复杂度: 总是 O(n²)
空间复杂度: O(1)
·6.5 插入排序
原理: 像打牌时整理手牌一样,每次把新牌插入到已排好序的牌中。
void InsertionSort(int array[], int n) {
for (int i = 1; i < n; i++) {
int key = array[i];
int j = i - 1;
while (j >= 0 && array[j] > key) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}
}
时间复杂度: 最好 O(n)(已有序),最坏 O(n²),平均 O(n²)(2023年9月判断第2题)
空间复杂度: O(1)(就地排序)
·6.6 三种排序对比
冒泡排序
稳定性:稳定
最好时间复杂度:O(n)
平均时间复杂度:O(n²)
最坏时间复杂度:O(n²)
空间复杂度:O(1)
选择排序
稳定性:不稳定
最好时间复杂度:O(n²)
平均时间复杂度:O(n²)
最坏时间复杂度:O(n²)
空间复杂度:O(1)
插入排序
稳定性:稳定
最好时间复杂度:O(n)
平均时间复杂度:O(n²)
最坏时间复杂度:O(n²)
空间复杂度:O(1)
·6.7 C++ 内置函数 sort()
int a[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
sort(a, a + 5); // 对前5个元素排序:{6,7,8,9,10,5,4,3,2,1}
(2023年12月判断第1题)
知识块⑦:文件操作
·7.1 文件重定向
freopen("input.txt", "r", stdin); // 从文件读取输入
freopen("output.txt", "w", stdout); // 输出到文件
判断题: “通过使用文件重定向操作,可以将程序中输出到cout的内容输出到文件中。”(2023年9月判断第10题) 答案:√。
·7.2 文件流操作
#include <fstream>
using namespace std;
// 写文件
ofstream fout;
fout.open("1.txt");
fout << "hello";
fout.close();
// 读文件
ifstream fin;
fin.open("1.txt");
string s;
fin >> s;
fin.close();
注意:ifstream 用于读,ofstream 用于写,不要搞混!(2023年12月判断第4题)
·7.3 四种输出重定向方式
练习题: 下面哪种方式不能实现将字符串输出重定向到文件log.txt?(2024年12月第14题)
A. freopen("log.txt","w",stdout); cout<<"..."; ← 可以
B. ofstream outFile("log.txt"); outFile<<"..."; ← 可以
C. C0 ← 不能!cout没有重定向到文件
D. 重定向cout的rdbuf() ← 可以
知识块⑧:异常处理
·8.1 异常处理的基本结构
try {
if (条件) throw runtime_error("错误信息");
} catch (runtime_error &e) {
cout << e.what();
}
·8.2 常见判断题
“一个try子句可以多个catch子句与之对应。”(2023年9月第13题) 答案:√。
“如果一个函数可能抛出异常,那么一定要在try子句里调用这个函数。”(2023年6月判断第6题) 答案:×。
“一个可能抛出异常的函数,调用它的位置没有在try子句中,会引起编译错误。”(2023年9月判断第8题) 答案:×。
03
PART
历年真题逐题分析
EXAMS · 真题
2023年6月试卷
域名常识★★
顶级域名是org
排序稳定性★★★
选择排序不稳定,冒泡和插入稳定
指针概念★★★
指针变量存地址,可指向指针变量
二维数组内存★★★
二维数组连续存放
函数概念★★★
函数必须有名字
变量作用域★★★
两个变量名可以相同,作用域不同
二维数组大小★★★
double[3][10] = 240字节
空指针+类型★★★
nullptr不指向任何地址,运行时错误
数组位置计算★★★★
array[1][2]和array[2][1]差8字节
位运算&★★★
6&3=2
指针赋值★★★★
a变{1,3,3,4,5}
二维数组参数★★★★
必须指定第二维int a[][4]
指针参数★★★★
传地址才能修改,选int *x, int *y
二维数组遍历★★★★
sum未初始化,输出无法确定
选择排序★★★★
填 array[min] > array[j]
判断题答案: × × × × √ × × × √ √
2023年9月试卷
计算机常识★★
App是应用软件
流程图★★★
输出5
冒泡排序复杂度★★★
平均O(n²)
指针概念★★★
可定义void*指针
多维数组★★★
可定义四维数组
函数调用★★★
必须提供足够的实际参数
作用域★★★
局部变量可以重名
二维数组大小★★★
char[3][10]=30字节
指针和地址★★★
指针p的值等于n的地址
三维数组位置★★★★★
较复杂
位运算~★★★★
~6=-7
指针赋值★★★★
a变{1,2,2,4,5}
异常处理★★★
一个try可对应多个catch
数组越界★★★★
fib[10]越界,输出不确定
冒泡排序★★★★
填int j=0; j<i-1; j++
判断题答案: √ × × √ √ × × × √ ×
2023年12月试卷
值传递★★★
子函数修改不影响主函数
数组+sort★★★
sort(a,a+5)后a={6,7,8,9,10,5,4,3,2,1}
字符串输出★★★
str[1]~str[4]输出“ESP”
二维数组遍历★★★
每行倒序输出
指针运算★★★★
p++指向arr[1]=2
指针加法★★★★
int*加1加4字节,0x6ffe14→0x6ffe18
指针解引用★★★★
*p=20*20=400
位运算★★★
5&2=0
字母数组初始化★★★
alpha[i]=alpha[i-1]+1
文件输出字节★★★
10个字符,共10字节
高精度加法★★★★
选D:c.push_back(t%10), t=t/10
链表类型判断★★★★
双向链表(有prev和next)
字典映射翻译★★★★
map应用
通信常识★★
通讯卫星→信号中继
贪心算法★★★★
田忌赛马
判断题答案: √ × × √ × √ √ √ × √
2024年3月试卷
引用传递★★★
f(a)是引用传递,会修改a的值
指针+sizeof★★★★
sizeof(x)=16,geSP[16]=‘n’
指针+类型转换★★★★
fnum[0]+fnum[1]=3.1
指针数组输出★★★★
第二行输出“024”
二维数组地址★★★★
a+1=0x6ffe00+12=0x6ffe0C
指针+字符串★★★★
p+5输出“e GESP!”
变量作用域★★★★
局部变量rc未初始化,输出不确定
递推算法识别★★
循环实现斐波那契是递推
素数判断条件★★★
i*i<=num
埃氏筛范围★★★★
i<=sqrt(n)
文件读取★★★★
“3.16”读为int→3
指针数组★★★★
第二行输出“024”
static关键字★★★
限定作用域
操作系统★★
鸿蒙是操作系统
计算机常识★★
王选→汉字激光照排
判断题答案: × × × × √ √ × × √ ×
2024年6月试卷
算法识别★★
循环实现斐波那契是迭代算法
贪心算法★★★
最少硬币组合是贪心算法
链表查找时间复杂度★★★
O(n)
双向链表头部插入★★★★
head->prev = p
数组地址★★★★
a+1=0x6ffe00+12=0x6ffe0C
文件路径★★★★
“/data/GESP.txt”是绝对路径
插入排序空间复杂度★★★★
O(1)不是O(n)
递归vs迭代效率★★★★
递归版效率并不更高
线性筛代码★★★★
for(int j=0; j<primes.size() && i*primes[j]<=n; j++)
线性筛时间复杂度★★★
O(n)
快速排序循环条件★★★★
while(i <= j)
分治算法概念★★★
分治将问题分成子问题解决
二分查找比较序列★★★★
39,79,90,81
高精度减法借位★★★★
a[i+1]--
归并排序比较次数★★★★
2n-1
判断题答案: × × × √ √ √ × × × √
2024年12月试卷
链表特性★★★
链表插入删除效率高
循环单链表★★★
最后一个节点指向第一个节点
虚拟头节点删除★★★★
dummyHead->next=head; cur=dummyHead
斐波那契复杂度★★★★
fibA O(n),fibB O(2ⁿ)
欧几里得调用顺序★★★★
gcd(24,36)→gcd(24,12)
质因数分解★★★★
for(int i=3; i*i<=n; i+=2)
埃氏筛理解★★★★
从i²开始标记
线性筛理解★★★★
时间复杂度O(n)
快速排序★★★★
通过递归对子问题求解
归并排序★★★★
最优/最差/平均都是O(n log n)
二分查找递归★★★★
终止条件包括left>right
二分查找左边界★★★★
right = middle
贪心分饼干★★★
result++; index--
输出重定向★★★★
普通cout不能重定向到文件
异常处理★★★★
抛出异常
判断题答案: × × × √ √ √ × √ √ ×
2025年3月试卷
链表特点★★★
链表不能随机访问
双向链表删除★★★★
四步操作顺序
双向循环链表初始化★★★★
head->next=tail, tail->prev=head
欧几里得算法步骤★★★
gcd(84,60)→gcd(60,24)→gcd(24,12)→gcd(12,0)
唯一分解定理★★★
30=2×3×5正确
线性筛条件★★★★
j<primes.size() && i*primes[j]<=n
递归栈溢出★★★
系统分配的栈空间溢出
递归vs迭代★★★
factorialB是迭代
排序稳定性★★★
选择排序不稳定
快排partition★★★★
if(arr[j]<pivot) { i++; swap(arr[i],arr[j]); }
二分猜数次数★★★
log₂100≈7次
二分mid计算★★
int mid = left + (right - left) / 2
贪心核心特征★★★
总是选择当前最优解
分治求最大值★★★★
正确实现分治
高精度乘法进位★★★★
int temp = c[k] + carry
判断题答案: × √ × × × √ × × × ×
2025年12月试卷
循环链表遍历★★★★
do-while + p != head
区块链插入★★★★
tail = newBlock
链表删除时间复杂度★★★★
双链表O(1),单链表O(n)
同余概念★★★
38-14=24,24不能被9整除
欧几里得算法★★★
递归版效率并不更高
唯一分解定理★★★
大于1的合数可以唯一分解
线性筛代码★★★★
for(int j=0; j<primes.size() && i*primes[j]<=n; j++)
排序稳定性★★★
归并排序通常是稳定的
归并排序特性★★★★
最坏情况也是O(n log n)
快排最坏复杂度★★★
O(n²)
lower_bound实现★★★★
逻辑正确
二分答案★★★★
if(check) r=mid else l=mid+1
递归vs迭代时空复杂度★★★★
时间复杂度相同O(n),空间复杂度不同
贪心任务调度★★★★
slot[t]=true; totalProfit+=task.profit
高精度加法★★★★
c.push_back(carry%10); carry/=10
判断题答案: × √ × × √ × √ × × √
2026年3月试卷
循环链表判空★★★★
头结点next指向自身
双向循环链表插入★★★★
选B
虚拟头节点删除★★★★
cur->next = del->next
欧几里得调用序列★★★
gcd(48,18)→gcd(18,12)→gcd(12,6)→gcd(6,0)
线性筛条件★★★★
j < primes.size()
埃氏筛i²原因★★★★
小于i²的倍数已被更小质因子筛过
二分答案★★★★
输出3
lower_bound★★★★
r = mid
递归栈溢出★★★★
栈溢出时程序会终止
二分答案★★★★
选B
分治复杂度★★★★
O(n log n)
归并排序合并★★★
A[i] <= B[j]
快排最坏复杂度★★★★
已排序+首元素pivot→O(n²)
排序比较★★★★
归并排序稳定,快排不稳定
高精度除法★★★★
rem %= b
判断题答案: × × × √ √ × √ × × ×
2026年6月试卷
循环链表插入★★★★
newNode->next=head->next; head->next=newNode
循环链表遍历★★★★
do-while + p != head
双链表删除★★★★
p->prev->next=p->next; p->next->prev=p->prev
欧几里得调用序列★★★
gcd(105,45)→gcd(45,15)→gcd(15,0)
线性筛break条件★★★★
i % primes[j] == 0
埃氏筛理解★★★
从每个素数出发,标记倍数
快速幂分治★★★
分治思想
因子2的个数★★★
40=2³×5,输出3
lower_bound★★★★
r = mid
二分答案★★★★
r = mid
快排partition★★★★
swap(arr[low], arr[i])
归并排序思想★★★
分两半分别排序再合并
merge调用次数★★★★
n-1次
贪心盲盒打包★★★★
l++; r--
高精度减法借位★★★★
a[i] += 10
04
PART
判断题高频陷阱
TRAPS · 判断
第1名:指针相关(约10次)
“指针变量本身不占用内存。”(2023年9月判断第1题) ×。指针变量也占用内存。
“指针变量只能指向基本类型变量,不能指向指针变量。”(2023年6月第3题) ×。
“可以定义指向void类型的指针,那没有意义。”(2023年9月第4题) ×。
第2名:函数参数传递(约8次)
“函数的参数默认以引用传递方式进行传递。”(2023年6月判断第3题) ×。默认值传递。
“通过引用传递的参数不会复制实际参数,因此不会额外占用内存。”(2023年9月判断第4题) √。
“一个函数没有被调用时,它的参数不占用内存。”(2023年6月判断第5题) √。
第3名:排序算法(约7次)
“冒泡排序是不稳定的。”(2023年6月第2题) ×。冒泡稳定。
“选择排序是不稳定的。” √。
“对N个元素的数组执行插入排序算法,通常的时间复杂度是O(N²)。”(2023年9月判断第2题) √。
第4名:数组概念(约6次)
“二维数组在内存中可以不是连续存放的。”(2023年6月第4题) ×。
“可以定义四维数组,但在解决实际问题时不可能用到。”(2023年6月判断第4题) ×。
第5名:文件操作(约5次)
“通过使用文件重定向操作,可以将程序中输出到cout的内容输出到文件中。”(2023年9月判断第10题) √。
第6名:异常处理(约4次)
“如果一个函数可能抛出异常,那么一定要在try子句里调用这个函数。”(2023年6月判断第6题) ×。
第7名:其他(约3次)
“字符常量‘0’和‘\\0’是等价的。”(2023年6月判断第8题) ×。‘0’=48,‘\\0’=0。
“Dev C++也是一个小型操作系统。”(2023年12月判断第9题) ×。是IDE。
“任何一个while循环都可以转化为等价的for循环。”(2023年12月判断第10题) √。
05
PART
编程题全分析
CODE · 编程题
各套真题编程题一览
2023年6月
编程题1:幸运数
考点:数位处理
编程题2:图像压缩
考点:数组统计、排序
2023年9月
编程题1:进制转换
考点:字符串处理
编程题2:变长编码
考点:位运算
2023年12月
编程题1:小杨的字典
考点:字符串、map
编程题2:田忌赛马
考点:贪心、排序
2024年3月
编程题1:成绩排序
考点:结构体排序
编程题2:B-smooth数
考点:筛法、数论
2024年6月
编程题1:黑白格
考点:二维数组
编程题2:小杨的幸运数字
考点:数论、筛法
2024年9月
编程题1:小杨的武器
考点:贪心
编程题2:挑战怪物
考点:数论
2024年12月
编程题1:奇妙数字
考点:质因数分解
编程题2:武器强化
考点:贪心、排序
2025年3月
编程题1:荒地开垦
考点:二维数组
编程题2:二阶矩阵
考点:矩阵运算
2025年6月
编程题1:排序问题
考点:排序算法
编程题2:文件操作
考点:文件读写
2025年9月
编程题1:字符串处理
考点:字符串操作
编程题2:数组操作
考点:数组遍历
2025年12月
编程题1:数字移动
考点:二分答案、贪心
编程题2:相等序列
考点:质因数分解
2026年3月
编程题1:有限不循环小数
考点:数论
编程题2:数据排序
考点:排序算法
2026年6月
编程题1:扫雷地图生成
考点:二维数组
编程题2:BMI指数排序
考点:结构体排序
编程必会模板
模板1:选择排序
void SelectionSort(int array[], int n) {
for (int i = 0; i < n - 1; i++) {
int min = i;
for (int j = i + 1; j < n; j++)
if (array[min] > array[j]) min = j;
int temp = array[min];
array[min] = array[i];
array[i] = temp;
}
}
模板2:冒泡排序
void BubbleSort(int array[], int n) {
for (int i = n; i >= 2; i--)
for (int j = 0; j < i - 1; j++)
if (array[j] > array[j + 1]) {
int t = array[j];
array[j] = array[j + 1];
array[j + 1] = t;
}
}
模板3:插入排序
void InsertionSort(int array[], int n) {
for (int i = 1; i < n; i++) {
int key = array[i];
int j = i - 1;
while (j >= 0 && array[j] > key) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}
}
模板4:文件读写(C++)
#include <fstream>
using namespace std;
// 读文件
ifstream fin; fin.open("input.txt"); int x; fin >> x; fin.close();
// 写文件
ofstream fout; fout.open("output.txt"); fout << x; fout.close();
模板5:递推——斐波那契数列
int fib[100]; fib[0] = 0; fib[1] = 1;
for (int i = 2; i < 100; i++) fib[i] = fib[i-1] + fib[i-2];
模板6:二维数组遍历
int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
sum += arr[i][j];
06
PART
高频易错题精选
TRAPS · 易错
单选题精选
1. 关于指针,以下说法不正确的是?(2023年6月第3题)
A. 指针变量中存储的是内存地址
B. 定义指针变量时必须指定其指向的类型
C. 指针变量只能指向基本类型变量,不能指向指针变量 ← 错误
D. 指针变量指向的内存地址不一定能够合法访问
答案:C
2. 一个二维数组定义为double array[3][10],则占用内存大小为?(2023年6月第7题)
A. 30 B. 60 C. 120 D. 240
解析: 3×10×8=240
3. 若函数声明为int f(int& x),对int a=3,哪个调用能改变a的值?(2024年3月第1题)
A. f(&a); B. f(*a); C. f(a); D. f(a-3);
答案:C。引用传递,直接传变量名即可。
4. 关于排序稳定性,以下说法正确的是?(2023年6月第2题)
A. 冒泡排序是不稳定的 B. 选择排序是不稳定的
C. 插入排序是不稳定的 D. 以上都不正确
答案:B
5. 下面C++代码执行后,输出的是?(2024年3月第2题)
int x[] = {2,0,2,4};
char geSP[] = "Grade Examination of SP";
cout << geSP[sizeof(x)] << endl;
A. G B. e C. n D. P
解析: sizeof(x)=16,geSP[16]=‘n’
判断题精选
1. 函数的参数默认以引用传递方式进行传递。(2023年6月判断第3题) ×
2. 指针变量本身不占用内存。(2023年9月判断第1题) ×
3. 字符常量‘0’和‘\\0’是等价的。(2023年6月判断第8题) ×
4. 二维数组在内存中可以不是连续存放的。(2023年6月第4题) ×
5. 通过使用文件重定向操作,可以将程序中输出到cout的内容输出到文件中。(2023年9月判断第10题) √
///
LAST
复习建议与考场技巧
PLAN · 冲刺
复习时间规划(距考试3周)
·第1周:基础打牢
| 指针(一) | ||
| 指针(二)+ 二维数组 | ||
| 结构体 + 函数 | ||
| 排序算法 | ||
| 递推算法 | ||
| 文件操作 + 异常处理 | ||
| 综合复习 |
·第2周:真题训练
·第3周:查漏补缺
复习“判断题高频陷阱”部分
熟背编程模板(6个必会模板)
限时模拟一套完整试卷(120分钟)
把之前的错题再过一遍
考场技巧
·做题顺序建议
单选题(15道,约30分钟)——不会的先跳过
判断题(10道,约15分钟)——注意“一定”“总是”“所有”这类绝对化词语
编程题(2道,约60分钟)——先读懂题目,再动手写代码
·编程题检查清单
☐ 变量都初始化了吗?(sum=0、min=0)
☐ 数组下标有没有越界?(最大下标是n-1)
☐ 指针解引用前检查是否为nullptr
☐ 二维数组的第二维大小指定正确吗?
☐ 排序算法的比较条件写对了吗?(升序还是降序)
☐ 输入输出格式跟题目要求一样吗?
☐ 文件流操作完成后关闭了吗?(fout.close())
☐ 有没有漏掉 return 0;?
DOMIAI
我是 DOMIAI,帮更多孩子成为 AI 时代原住民。
如果有收获,欢迎点赞、在看、转发三连,我们下篇见。
THANKS FOR READING