
很多准备GESP四级的朋友上来第一句就问“四级到底考什么是不是把三级语法学完就行” 我的回答通常比较直接三级看的是你会不会写C四级看的是你会不会用C解决问题。GESP四级正好卡在“语法熟练”到“算法入门”的分水岭上过了这道坎后面五级、六级学栈、队列、树、图才会顺过不去刷再多题也是原地踏步。这篇文章我会从四级考纲出发把排序、结构体、递归、STL、二分、贪心这些高频考点逐个拆开讲清原理、配上代码、列出避坑清单再给出一条可以照做的备考路线。不管你是零基础冲刺、还是已经在机构学过一阵子这篇内容都值得你花半小时认真看完。1. GESP四级到底考什么考纲拆解与学习重点1.1 四级的知识边界从“语法”到“算法”的真正跨越如果给GESP各级别画一条能力线一级到三级基本都在解决“语言问题”变量、分支、循环、数组、字符串、函数。到了四级考点开始明显向“算法思维”倾斜重点集中在几个板块排序算法选择排序、冒泡排序、插入排序以及计数排序。结构体与简单类结构体定义、数组存储、函数传参初步接触封装思想。递归与递推理解递归执行过程能写经典递归函数会用递推公式解决简单问题。STL基础重点掌握vector和sort理解迭代器的基本用法。二分查找在有序数组中查找目标理解二分答案的雏形。贪心算法能用局部最优策略解决简单的区间问题、分配问题。换句话说四级不是“更难的语法”而是“第一批真正能改变程序效率的思路”。同样一道排序题你可以用冒泡也可以调用sort还可以遇到特定数据用计数排序。考的就是你能不能根据数据范围选对方法。1.2 题型结构与命题趋势选择、判断、编程三块怎么分配精力GESP四级试卷由选择题、判断题、编程题三部分组成。选择题和判断题主要覆盖概念细节比如排序的稳定性、递归的终止条件、结构体成员访问方式、二分查找的边界条件。这些题目平时刷题不容易碰到必须有意识地背诵和辨析概念。编程题通常是2到3道风格非常稳定一道偏模拟或字符串处理一道偏排序或结构体应用一道偏贪心或二分查找。从近年考题看纯考语法的题目越来越少取而代之的是把语法藏进场景里比如用结构体管理学生成绩、用二分查找优化查询次数、用贪心安排活动时间表。所以备考时不要只盯着“能不能编译通过”更要训练“读完题能快速识别考点”的能力。1.3 与三级、五级的衔接为什么四级是关键分水岭不少同学三级轻松高分四级却考了两三次才过原因就是学习方式没切换。三级阶段的作业是“照着模板写代码”四级阶段的题目则要求你先抽象出数据模型再设计算法最后才是写代码。举一个很实在的例子同样处理“求n个数中出现次数最多的数”。三级思路是开计数数组硬统计四级就得多考虑一步——如果数很大、范围很广计数数组根本开不下怎么办这时候要么用排序后相邻相等元素统计要么用结构体加自定义排序解决。这就是四级真正的难点。它不考偏题怪题却会把简单问题包装成需要你“多想一层”的样子。2. 排序算法专项选择、冒泡、插入、计数一次讲透2.1 三种O(n²)排序的手写能力必须形成肌肉记忆GESP四级对排序的要求不是“会用sort就行”而是要求你能手写选择排序、冒泡排序和插入排序并且能说清它们的区别。原因很简单sort内部是优化过的快速排序虽然快但考察排序的原理时还是得回到最朴素的实现。拿冒泡排序举例最容易被忽视的是内层循环的边界条件。标准写法是这样的void bubbleSort(int a[], int n) { for (int i 0; i n - 1; i) { bool swapped false; for (int j 0; j n - i - 1; j) { if (a[j] a[j 1]) { swap(a[j], a[j 1]); swapped true; } } if (!swapped) break; // 本轮无交换说明已经有序 } }这里的swapped标记是一个经典的优化点也是考卷上喜欢挖坑的地方。如果数据本来就有序加上这个标记后冒泡排序的最好时间复杂度能降到O(n)。我见过很多学生在笔试题里问“冒泡排序最好情况复杂度”答案不是O(n²)而是O(n)就是靠这个优化实现的。选择排序和插入排序同样有各自的特征选择排序不稳定适合数据量小且不要求稳定性的场景插入排序稳定像整理扑克牌一样在近乎有序的数据上表现奇佳。2.2 计数排序唯一一个O(n)但容易写错的排序计数排序是四级考纲里的“偏门武器”。它不属于比较排序时间复杂度是O(nk)k是数据范围。很多学生第一次看到它都觉得神奇但写的时候又开始乱套。计数排序的核心思想就一句话用数组下标代表原数组的值数组里存的是这个值出现的次数。void countingSort(vectorint nums) { if (nums.empty()) return; int maxVal *max_element(nums.begin(), nums.end()); vectorint cnt(maxVal 1, 0); for (int x : nums) cnt[x]; int idx 0; for (int i 0; i maxVal; i) { while (cnt[i] 0) { nums[idx] i; cnt[i]--; } } }需要注意计数排序只适合数据范围不大的场景比如成绩、年龄、身高这类有限区间的数据。如果数据范围有负数或者特别大基础版就行不通了。我建议你在本子上写三遍这个模板考试时能直接默写因为编程题如果用上它效率优势非常明显。2.3 用sort函数STL的正确打开方式四级考试允许使用STL所以std::sort一定要熟练。至少要掌握三种用法排序整型数组、排序vector、对结构体按指定规则排序。结构体排序是编程题的高频考法代码通常长这样struct Student { string name; int score; int id; }; bool cmp(Student a, Student b) { if (a.score ! b.score) return a.score b.score; // 分数高的在前 return a.id b.id; // 分数相同按学号小的在前 } sort(stu, stu n, cmp);这里面有个初学者易错的坎比较函数cmp必须满足“严格弱序”也就是返回值必须表示“a是否应该排在b前面”不能出现a和b互为true的情况。比如比较分数时如果你写的是return a.score b.score当两个分数相等时ab和ba都成立sort行为就变成未定义了程序可能直接崩溃。这种错误在本地编译时不报错在评测系统里却会让你莫名超时或答案错误排查起来特别费劲。2.4 一张表记住四种排序稳定性和复杂度对照排序方法平均时间复杂度最好情况最坏情况是否稳定适用场景选择排序O(n²)O(n²)O(n²)不稳定简单但慢冒泡排序O(n²)O(n)O(n²)稳定近乎有序数据插入排序O(n²)O(n)O(n²)稳定数据量小计数排序O(nk)O(nk)O(nk)稳定数据范围小选择排序为什么不稳定因为它会把后面的小元素直接交换到前面可能打乱相同元素的相对顺序。这个知识点在选择题里反复出现记忆方式就是“选择交换不稳定”。3. 函数、递归与递推打开思路的第一步3.1 递归三要素与执行过程从栈的角度理解递归是GESP四级里很多同学觉得玄学的部分。其实递归的底层就是函数调用栈每调用一次函数系统就把当前状态压栈函数返回时再从栈里恢复现场。理解这一点后很多问题都会迎刃而解。写递归只需要盯住三件事终止条件什么时候不再调用自己直接返回结果。递归关系当前结果如何由更小规模的问题推导出来。递归参数每一层调用参数要朝着“更小”的方向变化。以经典斐波那契为例int fib(int n) { if (n 1) return n; // 终止条件 return fib(n - 1) fib(n - 2); // 递归关系 }这里必须提醒朴素递归的斐波那契在n稍微大一点时会指数级膨胀。fib(40)就已经需要跑好几秒fib(50)基本跑不完了。四级考试如果需要用斐波那契通常不会让你直接递归算而是让你用递推数组或者做记忆化处理。递归能帮你抓思路但绝不能不管效率直接提交。3.2 从递归到递推循环数组替代函数栈递推和递归的区别用一句话说就是递归是从上往下拆问题递推是从下往上推答案。斐波那契用递推写就是用一个数组滚动保存前两项long long f[55]; f[0] 0; f[1] 1; for (int i 2; i n; i) { f[i] f[i - 1] f[i - 2]; }这样做的好处是每个子问题只算一次时间复杂度O(n)而且不存在爆栈风险。类似的判断质数时也有人喜欢写递归试除但其实用循环更直接试除到sqrt(n)就可以停了在判断质数优化时常用的模板是for (int i 2; i * i n; i)注意用i*i时防止int溢出改用i n / i更安全。这些细节都可能在四级选择题里出现。3.3 经典递归问题速览汉诺塔、全排列、倒序输出四级阶段至少要看懂三个经典递归程序汉诺塔、全排列、倒序输出字符串。汉诺塔的代码非常短但理解它需要盯住“借助第三个柱子的过程”void hanoi(int n, char from, char mid, char to) { if (n 1) { cout from - to endl; return; } hanoi(n - 1, from, to, mid); cout from - to endl; hanoi(n - 1, mid, from, to); }建议你把n3代入在纸上画一遍递归树把所有过程补齐。这一步做完你的递归就真正通了。全排列问题则更接近四级编程题风格用递归加回溯可以输出一个数组的所有排列这类题本质上是为五级的深度优先搜索打基础。4. 结构体与类从面向过程到面向对象的关键跨越4.1 struct与函数传参为什么一定要用引用结构体在四级中的定位是“组织复杂数据”。考纲不要求你把面向对象学得多深但要会用结构体把相关联的数据捆绑在一起。比如学生信息包含姓名、语文成绩、数学成绩、总成绩用结构体存储后一次sort就能按任意维度排序代码可读性也瞬间提升。struct传给函数时默认是值传递也就是复制一份完整的结构体。如果结构体里成员较多频繁复制会拖慢程序。所以函数参数里建议写成const Student s这种形式既避免拷贝又防止误改void printStu(const Student s) { cout s.name s.score endl; }很多学生一开始不习惯引用符号但这是C相对C语言的一个实用性改进也是四级常考的概念点务必掌握。4.2 class封装与三个最容易犯的错四级对类的考察比较基础通常只要求“知道类是什么、能定义简单类”。比如定义一个口算题目的类包含题目字符串、答案和难度等级。但有几个坑几乎年年有人踩成员默认是私有的。struct的成员默认publicclass的成员默认private刚切换时经常忘记给数据成员加public结果主函数里stu.name直接编译失败。构造函数与类同名没有返回值。写了构造函数后它会在对象创建时自动执行适合初始化成员。this指针的含义。在成员函数里用this-score来访问成员可以避免参数名和成员名冲突。一个简单的类定义可以写成class Student { public: Student(string n, int s) : name(n), score(s) {} void print() { cout name score endl; } private: string name; int score; };考试中如果选择题问“private成员能否在外部访问”答案是否定的。这个“访问权限”概念是四级和三级最大的区别之一多花几分钟吃透很值得。4.3 结构体数组与sort搭配编程题经典套路模拟考试成绩排名的题目几乎每年都会以不同马甲出现。套路是固定的定义结构体、读入数据、写比较函数、sort排序、按格式输出。这里要额外注意并列排名的处理如果题目要求“分数相同则按学号升序”那比较函数里一定要写两行判断而不是只比一个字段。平时都练熟了考试时就能直接当“默写题”做把时间留给后面更难的题目。5. STL实用基础vector与sort让代码量骤减5.1 vector动态数组的使用要点四级允许使用STL后vector就成了最常用的容器。它比普通数组灵活的地方在于长度可变push_back可以动态追加元素。基本用法如下vectorint v; v.push_back(5); v.push_back(3); sort(v.begin(), v.end()); int size v.size(); for (int i 0; i v.size(); i) { cout v[i] ; }这里有一个经常在选择题里挖坑的点v.size()返回的是size_t类型是无符号整数。如果你写for (int i v.size() - 1; i 0; i--)当v为空时v.size() - 1会变成巨大的正数循环直接崩溃。安全写法是用for (int i (int)v.size() - 1; i 0; i--)或者干脆用下标逆序遍历时格外小心。这些小坑笔试时就是送命题。5.2 string与字符处理的常见操作四级编程题很大比例会涉及字符串处理。C的string类封装好了各种常用功能必须烂熟于心的有取子串substr(pos, len)查找find返回子串第一次出现位置找不到返回string::npos长度length()字符拼接直接用号string s GESP2025; string sub s.substr(4, 4); // 2025 if (s.find(2025) ! string::npos) { cout found endl; }还经常遇到“字符串数组初始化”的题目vector 可以直接用花括号初始化vector names {Alice, Bob, Cindy};。另外getline(cin, s)能读入包含空格的整行而cin s只能读到空格为止。读入混合数据时这是最大的坑我见过无数学生用cin s读带空格的名字结果输出全乱了所以在读整行前如果有数字输入记得先加一个cin.ignore()把缓冲区里的换行符清掉。5.3 四级阶段还需要认识的其他容器吗map、set、stack、queue这些容器严格来说在四级不是重点但有些考题会以“阅读理解”的形式出现比如给一段使用map的代码让你推结果。我的建议是至少能看懂map是什么——它存储键值对key唯一内部自动排序set存储不重复元素也有序。不要求你写得熟练但不能完全看不懂。如果你学有余力可以提前把stack和queue的常用操作过一遍这样备考五级时会轻松非常多。6. 二分查找与贪心思维四级最“提分”的两把刀6.1 二分查找的边界问题死循环的根源二分查找本身思想不难难的是写对边界。GESP选择题特别喜欢考“以下哪个是正确写法”答案差别往往就在一个等号或者一处1/-1上。我的建议是记住一套“左闭右开”模板考试时直接套int l 0, r n; // 查找区间 [l, r) while (l r) { int mid (l r) / 2; if (a[mid] target) r mid; else l mid 1; } // 结束后l就是第一个 target 的位置补充这种写法相当于C里的lower_bound。如果题目要求找大于等于目标值的第一个位置这个模板直接输出l即可如果要求找大于目标值的位置可以把条件改成a[mid] target。写二分时把人脑“想当然”的细节交给模板能减少大量隐蔽错误。编程题若明确提示数据有序或需要频繁查找就应该条件反射地去想二分。6.2 贪心算法局部最优如何凑成全局最优贪心是四级算法题里区分度最高的部分。它的核心思想是每一步都做当前看起来最好的选择最终得到全局最优解。但贪心不是“碰运气”它需要严格证明。四级阶段最常考的贪心场景有活动安排按结束时间排序、接水问题按时间短者优先、分糖果问题先排序再分配。活动安排问题的代码思路极简struct Act { int s, e; }; bool cmp(Act a, Act b) { return a.e b.e; // 按结束时间排序 } sort(acts, acts n, cmp); int ans 0, lastEnd 0; for (int i 0; i n; i) { if (acts[i].s lastEnd) { ans; lastEnd acts[i].e; } }为什么按结束时间排序是对的因为结束越早越能给后面的活动留出更多时间。这个直觉看起来简单但在考场上不少学生会错选成“按开始时间排序”。备考时多问自己一句“它的反例在哪”就能避开一类错误。6.3 贪心的反例意识不能“看起来对”就写平时刷题时遇到贪心题目一定要动手验证小数据。比如“硬币找零问题”在有些硬币面额下贪心不成立需要动态规划来解决四级不考动态规划但会通过选择题让你判断“贪心一定能得到最优解吗”。这种题考察的就是你对贪心局限性的认识。我的经验是做题前先用暴力枚举跑一个小数据如果贪心结果和暴力结果一致再提交贪心代码这个习惯能让你少交很多次罚时。7. 备考路线与常见失分点排查7.1 开发环境选择Dev-C还是VSCode环境对考试不直接加分但会影响平时练习效率。Dev-C安装简单考场上模拟体验真实VSCode功能更强适合长期学习但配置C/C环境需要花心思包括安装编译器、配置tasks.json和launch.json。四级阶段我的建议是用什么顺手就用什么不要为了“高级”而频繁换环境真正重要的是把编译运行快捷键练到肌肉记忆。考试前务必用官方模拟系统练一次熟悉提交和评测流程很多考生不是不会写而是不知道输出格式有多严格——多了个空格都可能是零分。7.2 三轮复习法基础、真题、错题怎么安排如果距离考试还有两个月左右可以参考下面这个节奏第一轮约3周梳理考纲知识点排序算法手写三遍左右结构体和STL每天练两个小题递归递推至少做掉10道经典题。第二轮约2周刷近年真题和模拟题每道编程题写完必须提交评测不满足于“本地能跑”。第三轮约1周整理错题本把选择题中的概念错题集中背诵编程题按题型归类重做。7.3 编程题常见失分点速查表问题类型具体表现解决办法数组越界开了a[100]却访问a[100]多开10个空间养成习惯变量未初始化sum、ans忘记赋0定义时同步初始化输入输出格式多空格、少换行、输出多余字符按样例严格比对结构体比较错误比较函数写了号只写严格小于/大于二分死循环mid更新条件不对套模板不要临时发挥递归爆栈递归层数过深改递推或改成循环忘记cin.ignoregetline前残留换行符读入数字后主动清空缓冲7.4 选择题判断题的背诵清单最后再整理一份考前背诵清单四种排序的稳定性与时间空间复杂度递归必须有终止条件否则栈溢出结构体与类的区别以及访问权限默认值vector的size()是无符号类型string的find找不到时返回npos二分查找要求数据有序贪心算法需要证明局部最优能推出全局最优。每个考点用一句话总结考前过一遍选择题拿分就会稳很多。根据我带学生的实际经验能一次通过四级的人往往不是刷题最多的而是每次错题后都能把原因抽象成一句话的那类同学。比如“凡是看到已经有序的数据就要想到插入排序的O(n)”“凡是遇到自定义排序先检查比较器是否符合严格弱序”。备考四级时你有多少次“原来这里写错了”的顿悟考试时就有多大把握。这份考点拆解与实操指南建议你收藏后立刻打开编译器从第一个排序模板开始一行一行敲出肌肉记忆。四级的难度不在天上而在脚下把每个模板吃透、把每类题目的套路写顺证书自然会来。