2026年3月 GESP C++ 6级
2026年3月 GESP C++ 6级认证考试真题(含编程操作题部分)
// questions
题目预览
下列关于 C++ 中类的描述,正确的是( )。
如果类没有用户声明的构造函数,那么编译器会隐式声明一个默认构造函数
类的析构函数可以被重载,一个类可以有多个析构函数
类中的所有成员都必须声明为 public
类和结构体在 C++ 中没有区别,包括默认访问权限也相同
下列代码中,s1->draw(); 和 s2->draw(); 输出不同结果的主要原因是( )。
class Shape {
public:
virtual void draw() {
cout << "绘制图形" << endl;
}
virtual ~Shape() {}
};
class Circle : public Shape {
public:
void draw() override {
cout << "绘制圆形" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "绘制矩形" << endl;
}
};
int main() {
Shape* s1 = new Circle();
Shape* s2 = new Rectangle();
s1->draw();
s2->draw();
delete s1;
delete s2;
return 0;
}
draw() 是普通成员函数
Shape 中的 draw() 被声明为虚函数
Circle 和 Rectangle 中使用了 public 继承
指针变量名不同
下面的代码在 main() 中有一行会导致编译错误,请找出来。
class Pet {
public:
Pet(string n, int a) : name(n), age(a) {}
string getName() { return name; }
void birthday() { age++; }
private:
string name;
int age;
};
int main() {
Pet cat("奶茶", 2);
cout << cat.getName(); // ①
cat.birthday(); // ②
cat.name = "大橘"; // ③
cout << cat.getName(); // ④
}
第 111 行
第 222 行
第 333 行
第 444 行
游乐园的过山车每次限坐 444 人,用循环队列管理排队(容量 MAX=5MAX = 5MAX=5,空一格判满)。下面代码执行后,循环队列是否已满?rearrearrear 的值是多少?
const int MAX = 5;
int queue[MAX];
int front = 0, rear = 0;
// 入队
void enqueue(int x) {
queue[rear] = x;
rear = (rear + 1) % MAX;
}
// 出队
void dequeue() {
front = (front + 1) % MAX;
}
int main() {
enqueue(1); enqueue(2); enqueue(3); enqueue(4);
dequeue(); dequeue();
enqueue(5); enqueue(6);
}
已满,rear=1rear = 1rear=1
未满,rear=1rear = 1rear=1
已满,rear=2rear = 2rear=2
未满,rear=4rear = 4rear=4
在以下计算机系统应用场景中,最适合使用循环队列的是( )。
函数调用过程中,保存局部变量和返回地址
表达式求值中的运算符优先级处理
操作系统中的进程优先级调度(高优先级先执行)
生产者和消费者问题中的共享缓冲区
在二叉搜索树(BST)中,若中序遍历的序列为{1, 2, 3, 4, 5},且先序遍历的第一个序列元素为3,则下列说 法正确的是( )。
该树一定是一棵完全二叉树。
元素4和5不可能是兄弟节点。
元素1所在节点的深度可能大于3(根节点深度为1)。
元素2一定是元素1的⽗节点。
某二叉树共有 101010 个结点,记为 AAA ~ JJJ,已知它的先序遍历序列为:AAA BBB DDD HHH III EEE CCC FFF JJJ GGG,中序遍历序列为:HHH DDD III BBB EEE AAA FFF JJJ CCC GGG,则该二叉树的后序遍历序列是( )。
HHH III DDD EEE BBB JJJ FFF GGG CCC AAA
HHH III DDD BBB EEE JJJ FFF GGG CCC AAA
III HHH DDD EEE BBB JJJ FFF GGG CCC AAA
HHH III DDD EEE BBB FFF JJJ GGG CCC AAA
下列关于树的遍历的说法中,正确的一项是( )。
对任意一棵树进行深度优先遍历,所得序列一定唯一。
已知一棵二叉树的先序遍历和后序遍历序列,可以唯一确定这棵二叉树。
已知一棵二叉树的先序遍历和中序遍历序列,可以唯一确定这棵二叉树。
已知一棵二叉树的先序遍历序列,可以唯一确定这棵二叉树。
有 666 个字符,它们出现的次数分别为:{2,3,3,4,6,8}\{2, 3, 3, 4, 6, 8\}{2,3,3,4,6,8},现在用哈夫曼编码为这些字符编码,最小加权路径长度 WPL(每个字符的出现次数 ×\times× 它的编码长度,再把每个字符结果加起来)的值为( )。
585858
606060
626262
646464
对 nnn 个不同符号的符号进行哈夫曼编码。若生成的哈夫曼树共有 mmm 个结点,则 mmm 的值是()。
606060
585858
575757
565656
关于格雷编码(Gray Code),下列说法正确的是( )。
格雷编码中,编码位数越多,相邻编码之间变化的位数也越多
格雷编码中,相邻两个编码的二进制位恰好有一位不同
格雷编码就是把普通二进制编码按位取反后得到的结果
格雷编码不能用于数字电路和状态转换的设计中
给定一棵二叉树,采用广度优先搜索 (BFS) 算法,返回右视图所有节点的值。其中右视图定义为:二叉树的右视图是从树的右侧看过去时可见的节点集合,即右视图中的每个节点都是某一层中最右侧的节点。
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};
vector<int> rightSideView(TreeNode* root) {
unordered_map<int, int> rightmostValueAtDepth;
int max_depth = -1;
queue<TreeNode*> nodeQueue;
queue<int> depthQueue;
nodeQueue.push(root);
depthQueue.push(0);
while (!nodeQueue.empty()) {
TreeNode* node = nodeQueue.front(); nodeQueue.pop();
int depth = depthQueue.front(); depthQueue.pop();
if (node != NULL) {
max_depth = max(max_depth, depth);
rightmostValueAtDepth[depth] = node->val;
nodeQueue.push(node->left);
nodeQueue.push(node->right);
depthQueue.push(________);
depthQueue.push(________);
}
}
vector<int> rightView;
for (int depth = 0; ________; ++depth) {
rightView.push_back(rightmostValueAtDepth[depth]);
}
return rightView;
};
depth
depth
depth < max_depth
depth + 1
depth + 1
depth <= max_depth
depth + 1
depth + 1
depth < max_depth
depth
depth
depth <= max_depth
下列关于树的深度优先搜索(DFS)的说法中,正确的是( )。
对树进行 DFS 时,一定是按层从上到下依次访问结点
对任意一棵树进行 DFS,得到的遍历序列唯一
对一棵树进行 DFS 时,常借助递归或栈实现
DFS 只能用于二叉树,不能用于普通树
小朋友们去邻里拜年,每个家里有不同数量的糖果。规则是:不能连续进入两个相邻的房子(即不能同时取相邻两家的糖果)。目标是拿到最多糖果。以下是代码实现,请补全横线。
int visit(vector<int>& nums) {
if (nums.empty()) {
return 0;
}
int size = nums.size();
if (size == 1) {
return nums[0];
}
vector<int> dp = vector<int>(size, 0);
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
for (int i = 2; i < size; i++) {
dp[i] = ______; // 在此处填写代码
}
return dp[size - 1];
}
dp[i] = dp[i - 1] + nums[i];
dp[i] = max(dp[i - 1], dp[i - 2] * nums[i]);
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
dp[i] = dp[i - 2] + nums[i];
元宵节晚上,小朋友沿着一条发光石板路前进,每次可向前走 111 块或 222 块石板。动态规划定义如下:
dp[i] = dp[i - 1] + dp[i - 2],下面关于 dp[i] 的含义最合适的是( )。
走到第 iii 块石板的不同走法数量
走到第 iii 块石板时,已经走过的石板总数
从第 iii 块石板走回起点的最少步数
从第 iii 块石板走回起点的最大步数
下面定义了一个表示二维坐标点的类 Point,并提供了一个带参数的构造函数,但第 ② 行 Point b; 会调用编译器自动生成的默认构造函数,将 b.x 和 b.y 被初始化为 0.00.00.0,程序可以正常编译运行。
class Point {
public:
double x, y;
Point(double px, double py) : x(px), y(py) {}
void print() {
cout << "(" << x << ", " << y << ")";
}
};
int main() {
Point a(3.0, 4.0); // ①
Point b; // ②
a.print();
}
C++ 中的继承支持单继承和多继承,但子类无法直接访问父类的私有成员。
对如下结构的树,执行 travel 函数,输出结果是 111 222 333 444 555。
1
/ \
2 3
/ \
4 5
struct Node {
int val;
Node *left, *right;
Node(int v) : val(v), left(nullptr), right(nullptr) {}
};
void travel(Node* root) {
if (!root) return;
stack<Node*> s;
s.push(root);
while (!s.empty()) {
Node* cur = s.top(); s.pop();
cout << cur->val << " ";
if (cur->right) s.push(cur->right);
if (cur->left) s.push(cur->left);
}
}
若所有字符出现频率相同,则哈夫曼编码一定会得到完全二叉树。
哈夫曼编码是一种变长的前缀编码,在解码时不需要额外的分隔符就能唯一还原,这是因为在哈夫曼树中,任何一个字符的叶子结点都不会成为另一个字符结点的祖先。
在 C++ 中使用一维数组 vector<int> tree 存储按层序遍历的完全二叉树时,若根节点存储在 tree[0],则对于任意非空节点 tree[i],其右孩子(如果存在)必然位于 tree[2 * i + 2]。
在 C++ 中使用栈来非递归地实现二叉树的前序遍历时,为了保证遍历顺序正确,在处理完当前结点后,应该先将该结点的左孩子压入栈中,然后再将右孩子压入栈中。
设二叉树共有 nnn 个结点,函数 preorderTraversal 以下代码的时间复杂度为 O(n)O(n)O(n) ,空间复杂度为 O(n)O(n)O(n) 。
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};
void preorder(TreeNode *root, vector<int> &res) {
if (root == nullptr) {
return;
}
res.push_back(root->val);
preorder(root->left, res);
preorder(root->right, res);
}
vector<int> preorderTraversal(TreeNode *root) {
vector<int> res;
preorder(root, res);
return res;
};
下列代码实现了一个 000-111 背包的一维动态规划代码,内层循环是经典的逆序写法。若将内层循环改成正序遍历(即 for (int j = w[i]; j <= W; j++)),仍能得到正确答案。
int main() {
int W = 5;
int w[] = {2, 3, 4};
int v[] = {10, 1, 1};
int n = 3;
int dp[6] = {0};
for (int i = 0; i < n; i++) {
for (int j = W; j >= w[i]; j--) { // ← 逆序!
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
cout << dp[W];
}
在动态规划问题中,状态空间相同且没有重复计算的情况下,“状态转移方程+递推”与“递归+记忆化搜索”的时间复杂度通常相同。
试题名称:选数
时间限制:1.0 s | 内存限制:512.0 MB
题目描述
给定两个包含 nnn 个整数的数组 a=[a1,…,an]a=[a_1,\dots,a_n]a=[a1,…,an] 与 b=[b1,…,bn]b=[b_1,\dots,b_n]b=[b1,…,bn]。你需要指定若干下标 p1<⋯<pkp_1\lt \cdots\lt p_kp1<⋯<pk(1≤k≤n1\leq k\leq n1≤k≤n)使得以下条件成立:
- 1≤pi≤n1\leq p_i\leq n1≤pi≤n(1≤i≤k1\leq i\leq k1≤i≤k);
- pi+1≥pi+bpip_{i+1}\geq p_i+b_{p_i}pi+1≥pi+bpi(1≤i<k1\leq i< k1≤i<k)。
你需要在满足以上条件的前提下最大化 ∑i=1kapi\sum_{i=1}^k a_{p_i}∑i=1kapi,也即最大化数组 aaa 对应下标的整数之和。
输入格式
第一行,一个正整数 nnn,表示数组长度。
第二行,nnn 个正整数 a1,a2,…,ana_1,a_2,\dots,a_na1,a2,…,an,表示数组 aaa。
第三行,nnn 个正整数 b1,b2,…,bnb_1,b_2,\dots,b_nb1,b2,…,bn,表示数组 bbb。
输出格式
一行,一个整数,表示在满足下标条件的前提下,数组 aaa 对应下标的整数之和的最大值。
样例输入 #1
4
1 2 3 4
3 3 1 1
样例输出 #1
7
样例输入 #2
6
1 1 4 5 1 4
1 2 3 2 1 0
样例输出 #2
11
说明/提示
对于 40%40\%40% 的测试点,保证 2≤n≤1032\leq n\leq 10^32≤n≤103。
对于所有测试点,保证 2≤n≤1052\leq n\leq 10^52≤n≤105,0≤ai≤1090\leq a_i\leq 10^90≤ai≤109,0≤bi≤n0\leq b_i\leq n0≤bi≤n。
试题名称:完全二叉树
时间限制:1.0 s | 内存限制:512.0 MB
题目描述
给定一棵包含 nnn 个结点的有根二叉树,结点依次以 1,2,…,n1,2,\dots,n1,2,…,n 编号,根结点编号为 111。
对于结点 iii,其左儿子的编号记为 lil_ili,右儿子编号记为 rir_iri。特别地,如果左儿子不存在则 li=0l_i=0li=0,如果右儿子不存在则 ri=0r_i=0ri=0。
树中每个结点都对应一棵以其为根的子树。请你求出给定有根树的所有 nnn 棵子树中,有多少棵子树是完全二叉树。
输入格式
第一行,一个正整数 nnn,表示有根二叉树结点数量。
接下来 nnn 行,每行两个正整数 li,ril_i,r_ili,ri,表示结点 iii 的左儿子编号和右儿子编号。
输出格式
输出一行,一个整数,表示所有子树中完全二叉树的数量。
样例输入 #1
4
2 3
4 0
0 0
0 0
样例输出 #1
4
样例输入 #2
4
2 3
0 0
4 0
0 0
样例输出 #2
3
说明/提示
对于 40%40\%40% 的测试点,保证 1≤n≤5001\leq n\leq 5001≤n≤500。
对于所有测试点,保证 1≤n≤1051\leq n\leq 10^51≤n≤105。