
💪「艾墨舟编程小先锋」专为GESP考生打造的免费题库小程序。涵盖图形化/Python/C++全真题,支持真题模考、考前预测、错题整理与学习统计,一站式攻克客观题。
📋 内容概览
本文包含2026年3月GESP C++五级考试15道单选题的解析,精准匹配考纲知识点,附解题技巧与易错点提示。
🎯 试题解析
───── ✨ 第1题 ✨ ─────
📖 题目
关于单链表、双链表和循环链表,下列说法正确的是( )。A. 在单链表中,若已知任意结点的指针,则可以在O(1)时间内删除该结点。B. 循环链表中一定不存在空指针。C. 在循环双链表中,尾结点的next指针一定为nullptr。D. 在带头结点的循环单链表中,判定链表是否为空只需判断头结点的next是否指向自身。
📌 大纲对应知识点:线性表(链表)🎯 考查目标:掌握各类链表的结构特性和操作逻辑
📋 选项详解
⭐ 答案:D📌 知识点:链表结构特性
💡 解题小贴士:循环链表的核心特征是尾结点与头结点相连,带头结点的空表头结点的next必然指向自身。
───── ✨ 第2题 ✨ ─────
📖 题目
双向循环链表中要在结点p之前插入新结点s(均非空),以下指针操作正确的是( )。A.s->next = p;p->prev = s;p->next = s;s->prev = p;B.s->prev = p;s->next = p->next;p->next->prev = s;p->next = s;C.s->next = p;s->prev = p->prev;p->prev->next = s;p->prev = s;D.s->next = p;s->prev = nullptr;p->prev = s;
📌 大纲对应知识点:双链表的插入操作🎯 考查目标:掌握双链表插入时的指针修改顺序
📋 选项详解
⭐ 答案:C📌 知识点:双链表插入操作
💡 解题小贴士:双链表插入结点口诀:先连新结点两端,再改旧结点的前后指针,避免断链。
───── ✨ 第3题 ✨ ─────
📖 题目
下面函数用“哑结点”统一处理删除单向链表中的头结点与中间结点。横线处应填( )。
struct Node{ int val; Node* next; Node(int v):val(v),next(nullptr){}};Node* eraseAll(Node* head, int x){ Node dummy(0); dummy.next = head; Node* cur = &dummy; while(cur->next){ if(cur->next->val == x){ Node* del = cur->next; ______________________ delete del; }else cur = cur->next; } return dummy.next;}A. cur = cur->next;B. cur->next = del->next;C. del->next = cur->next;D. cur->next = nullptr;
📌 大纲对应知识点:单链表的删除操作🎯 考查目标:掌握哑结点法删除链表结点的核心逻辑
📋 选项详解
⭐ 答案:B📌 知识点:单链表删除操作
💡 解题小贴士:删除链表结点的核心是让待删结点的前驱直接指向待删结点的后继,跳过待删结点。
───── ✨ 第4题 ✨ ─────
📖 题目
对如下代码实现的欧几里得算法(辗转相除法),执行gcd(48, 18)得到的调用序列为( )。
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b);}A. gcd(48,18) -> gcd(18,12) -> gcd(12,6) -> gcd(6,0)B. gcd(48,18) -> gcd(30,18) -> gcd(12,18)C. gcd(48,18) -> gcd(18,30) -> gcd(30,6)D. gcd(48,18) -> gcd(12,18) -> gcd(6,12)
📌 大纲对应知识点:递归函数、数论(最大公约数)🎯 考查目标:掌握辗转相除法的执行流程
📋 选项详解
⭐ 答案:A📌 知识点:递归函数、欧几里得算法
💡 解题小贴士:辗转相除法核心:gcd(a,b) = gcd(b, a mod b),直到b为0时返回a。
───── ✨ 第5题 ✨ ─────
📖 题目
下面代码实现了欧拉(线性)筛,横线处应填写( )。
vector<int> euler_sieve(int n) { vector<bool> is_composite(n + 1, false); vector<int> primes; for (int i = 2; i <= n; i++) { if (!is_composite[i]) primes.push_back(i); for (int j = 0; __________________________ && (long long)i * primes[j] <= n; j++) { is_composite[i * primes[j]] = true; if (i % primes[j] == 0) break; } } return primes;}A. j <= nB. j < sqrt(n)C. j < primes.size()D. j < i
📌 大纲对应知识点:数论(素数筛法)🎯 考查目标:掌握欧拉筛的核心实现逻辑
📋 选项详解
⭐ 答案:C📌 知识点:欧拉筛法
💡 解题小贴士:欧拉筛内层循环遍历已存储的素数,当i能整除当前素数时停止,保证每个合数只被最小质因子筛一次。
───── ✨ 第6题 ✨ ─────
📖 题目
埃氏筛中将内层循环从j = ii开始而不是j = 2i的主要原因是( )。
vector<int> eratosthenes_sieve(int n) { vector<bool> is_composite(n + 1, false); vector<int> primes; for (int i = 2; i <= n; i++) { if (is_composite[i]) continue; primes.push_back(i); for (long long j = (long long)i * i; j <= n; j += i) is_composite[j] = true; } return primes;}A. 因为2i一定不是合数B. ii一定是质数C. 小于i*i的i的倍数已被更小质因子筛过D. 这样可以把时间复杂度降为O(n)
📌 大纲对应知识点:数论(素数筛法)🎯 考查目标:理解埃氏筛的优化逻辑
📋 选项详解
⭐ 答案:C📌 知识点:埃氏筛法优化
💡 解题小贴士:埃氏筛从i*i开始是为了避免重复标记更小的倍数,减少重复操作,但时间复杂度仍高于线性筛。
───── ✨ 第7题 ✨ ─────
📖 题目
下面程序的运行结果为( )。
bool check(int n, int a[], int k, int dist) { int cnt = 1; int last = a[0]; for (int i = 1; i < n; i++) { if (a[i] - last >= dist) { cnt++; last = a[i]; } } return cnt >= k;}int solve(int n, int a[], int k) { std::sort(a, a + n); int l = 0; int r = a[n - 1] - a[0]; while (l < r) { int mid = (l + r + 1) / 2; if (check(n, a, k, mid)) l = mid; else r = mid - 1; } return l;}int main() { int a[] = {1, 2, 8, 4, 9}; int n = 5; int k = 3; std::cout << solve(n, a, k) << std::endl; return 0;}A. 2B. 3C. 4D. 5
📌 大纲对应知识点:二分答案🎯 考查目标:掌握二分答案的应用场景和执行流程
📋 选项详解
⭐ 答案:B📌 知识点:二分答案、贪心校验
💡 解题小贴士:最大化最小值类问题通常用二分答案,校验函数用贪心策略尽可能选点,判断是否满足数量要求。
───── ✨ 第8题 ✨ ─────
📖 题目
在升序数组中查找第一个大于等于x的位置,下面循环中横线应填( )。
int lowerBound(const vector<int>& a, int x){ int l=0, r=a.size(); while(l<r){ int mid = l + (r - l)/2; if(a[mid] >= x) _____________; else l = mid + 1; } return l;}A. r = mid;B. r = mid - 1;C. l = mid;D. l = mid + 1;
📌 大纲对应知识点:二分查找🎯 考查目标:掌握lower_bound的实现逻辑
📋 选项详解
⭐ 答案:A📌 知识点:二分查找(lower_bound)
💡 解题小贴士:lower_bound左闭右开区间写法口诀:大于等于往左收(r=mid),小于往右走(l=mid+1)。
───── ✨ 第9题 ✨ ─────
📖 题目
关于递归函数调用,下列说法错误的是( )。A. 递归调用层次过深时,可能会耗尽栈空间导致栈溢出B. 尾递归函数可以通过编译器优化来避免栈溢出C. 所有递归函数都可以通过循环结构来改写,从而避免栈溢出D. 栈溢出发生时,程序会抛出异常并可以继续执行后续代码
📌 大纲对应知识点:递归函数🎯 考查目标:理解递归调用的底层特性和栈溢出问题
📋 选项详解
⭐ 答案:D📌 知识点:递归调用、栈溢出
💡 解题小贴士:栈溢出是未定义行为,程序会直接终止,不会正常抛出可捕获的异常。
───── ✨ 第10题 ✨ ─────
📖 题目
给定n根木头,第i根长度为a[i]。要切成不少于m段等长木段,求最大可能长度,则横线上应填写( )。
const int MAXN = 100005;long long a[MAXN];int n, m;bool check(long long x){ long long cnt = 0; for(int i = 1; i <= n; i++){ if(x == 0) return true; cnt += a[i] / x; if(cnt >= m) return true; } return false;}int main(){ cin >> n >> m; long long mx = 0; for(int i = 1; i <= n; i++){ cin >> a[i]; mx = max(mx, a[i]); } long long l = 1, r = mx; long long ans = 0; while(l <= r){ long long mid = l + (r - l) / 2; if(check(mid)){ ans = mid; ______________________ }else{ ______________________ } } cout << ans << endl; return 0;}A. l = mid + 1; r = mid - 1;B. l = mid - 1; r = mid + 1;C. l = mid + 1; r = mid;D. l = mid; r = mid + 1;
📌 大纲对应知识点:二分答案🎯 考查目标:掌握最大化可行值的二分边界调整逻辑
📋 选项详解
⭐ 答案:A📌 知识点:二分答案
💡 解题小贴士:最大化问题二分口诀:可行则尝试更大(l=mid+1),不可行则缩小(r=mid-1),每次可行时记录答案。
───── ✨ 第11题 ✨ ─────
📖 题目
下面代码用分治求 “最大连续子段和”,其时间复杂度为( )。
int solve(vector<int>& a, int l, int r){ if(l == r) return a[l]; int mid = l + (r - l) / 2; int left = solve(a, l, mid); int right = solve(a, mid + 1, r); int sum = 0, lmax = INT_MIN; for(int i = mid; i >= l; i--){ sum += a[i]; lmax = max(lmax, sum); } sum = 0; int rmax = INT_MIN; for(int i = mid + 1; i <= r; i++){ sum += a[i]; rmax = max(rmax, sum); } return max({left, right, lmax + rmax});}A. O(n)B. O(n log n)C. O(n²)D. O(log n)
📌 大纲对应知识点:分治算法、时间复杂度分析🎯 考查目标:掌握分治算法的时间复杂度计算
📋 选项详解
⭐ 答案:B📌 知识点:分治算法、时间复杂度
💡 解题小贴士:分治时间复杂度用主定理计算,T(n) = 2T(n/2) + O(n),符合主定理情况2,结果为O(n log n)。
───── ✨ 第12题 ✨ ─────
📖 题目
游戏大赛决赛,两组选手分别按得分从小到大排好队,现在要把他们合并成一个有序排行榜。A组:A = {12, 35, 67, 89}, B组:B = {20, 45, 55, 78},下面是归并合并函数的核心循环,横线处应填入( )。
int i = 0, j = 0;vector<int> result;while (i < A.size() && j < B.size()) { if (___________________) { result.push_back(A[i++]); } else { result.push_back(B[j++]); }}while (i < A.size()) { result.push_back(A[i++]);}while (j < B.size()) { result.push_back(B[j++]);}A. A[i] >= B[j]B. A[i] <= B[j]C. i >= jD. i <= j
📌 大纲对应知识点:归并排序🎯 考查目标:掌握归并排序中合并两个有序数组的逻辑
📋 选项详解
⭐ 答案:B📌 知识点:归并排序、双指针
💡 解题小贴士:合并两个升序数组口诀:双指针分别指向两个数组头部,每次选较小的元素放入结果,指针后移。
───── ✨ 第13题 ✨ ─────
📖 题目
有n位同学的成绩已经从小到大排好序,现在对它执行下面这段以第一个元素为pivot的快速排序,请问此次排序的时间复杂度是( )。
void quicksort(vector<int>& a, int l, int r) { if (l >= r) return; int pivot = a[l]; int i = l, j = r; while (i < j) { while (i < j && a[j] >= pivot) j--; while (i < j && a[i] <= pivot) i++; if (i < j) swap(a[i], a[j]); } swap(a[l], a[i]); quicksort(a, l, i - 1); quicksort(a, i + 1, r);}A. O(n)B. O(n log n)C. O(n²)D. O(log n)
📌 大纲对应知识点:快速排序、时间复杂度分析🎯 考查目标:理解快速排序的最坏时间复杂度场景
📋 选项详解
⭐ 答案:C📌 知识点:快速排序、时间复杂度
💡 解题小贴士:快速排序最坏情况出现在每次划分极度不均(如有序数组选首尾为枢轴),此时退化为冒泡排序,复杂度O(n²)。
───── ✨ 第14题 ✨ ─────
📖 题目
下面关于排序算法的描述中,不正确的是 ( ) 。A. 冒泡排序和插入排序都是稳定的排序算法B. 快速排序和归并排序都是不稳定的排序算法C. 冒泡排序和插入排序最好时间复杂度均为O(n)D. 归并排序在最好、最坏和平均三种情况的时间复杂度均为O(n log n)
📌 大纲对应知识点:排序算法特性🎯 考查目标:掌握常见排序算法的稳定性、时间复杂度特性
📋 选项详解
⭐ 答案:B📌 知识点:排序算法特性
💡 解题小贴士:稳定排序口诀:冒(冒泡)插(插入)归(归并)基(基数),其余均为不稳定排序。
───── ✨ 第15题 ✨ ─────
📖 题目
下面代码实现两个整数除法,其中被除数为一个“大整数”,用字符串表示,除数是一个小整数,用int表示,则横线处应该填写( )。
int main(){ string s; int b; cin >> s >> b; vector<int> a; for(char c : s){ a.push_back(c - '0'); } vector<int> c; long long rem = 0; for(int i = 0; i < a.size(); i++){ rem = rem * 10 + a[i]; int q = rem / b; c.push_back(q); ______________________ } int pos = 0; while(pos < c.size() - 1 && c[pos] == 0) pos++; for(int i = pos; i < c.size(); i++){ cout << c[i]; } cout << endl; cout << rem << endl; return 0;}A. rem /= b;B. rem %= b;C. rem = b;D. rem = q;
📌 大纲对应知识点:高精度运算🎯 考查目标:掌握高精度除以低精度的核心逻辑
📋 选项详解
⭐ 答案:B📌 知识点:高精度除法
💡 解题小贴士:高精度除以低精度口诀:从高位到低位逐位计算,余数乘以10加当前位,除以除数得商,保留余数继续计算。
📝 学习建议
本次考试核心考点涵盖:线性表(链表操作)、数论(素数筛、最大公约数)、二分算法(二分查找、二分答案)、排序算法(快速排序、归并排序)、分治算法、高精度运算等。复习建议:1. 熟练掌握链表的插入、删除操作,注意避免断链和内存泄漏2. 掌握埃氏筛和欧拉筛的实现原理和优化逻辑,理解时间复杂度差异3. 重点练习二分查找的各类变体(lower_bound、upper_bound)和二分答案的应用场景4. 熟悉常见排序算法的时间复杂度、稳定性和适用场景5. 多做分治、高精度类的编程题,提高代码实现能力
💪 更多真题练习、薄弱点诊断,欢迎使用「GESP练题小程序」,助你高效备考GESP等级考试。
📚 学而不思则罔,思而不学则殆。 —— 孔子