在面向对象编程中,类是一种重要的概念。下面关于类的描述中,不正确的是()。
D:错误项。类通过继承可以扩展属性和方法,派生类会新增或重写成员,并非定义后不可修改;A 类是抽象模板、B 含属性与方法、C 可实例化均正确。
哈夫曼编码是一种数据压缩算法。以下关于哈夫曼编码的描述中,不正确的是()。
B:错误项。构造哈夫曼树时频率越低的字符离根越远、编码越长,B 把远近关系说反了;A 变长编码、C 贪心合并最小两权、D 前缀码可唯一解码均正确。
以下代码实现了树的哪种遍历方式?
01void traverse(TreeNode* root) { 02 if (root == nullptr) return; 03 cout << root->val << " "; 04 traverse(root->left); 05 traverse(root->right); 06}
A:前序遍历。函数先输出根结点值,再递归遍历左子树、右子树,访问顺序为根左右,属于前序遍历(先根遍历)。,先访问根是其特征。
以下关于完全二叉树的代码描述,正确的是()。
01bool isCompleteTree(TreeNode* root) { 02 if (root == nullptr) return true; 03 queue<TreeNode*> q; 04 q.push(root); 05 bool hasNull = false; 06 while (!q.empty()) { 07 TreeNode* node = q.front(); 08 q.pop(); 09 if (node == nullptr) { 10 hasNull = true; 11 } else { 12 if (hasNull) return false; 13 q.push(node->left); 14 q.push(node->right); 15 } 16 } 17 return true; 18}
B:该代码用 BFS 层序遍历,一旦遇到空结点置 hasNull 后,若再出现非空结点就返回 false,正是完全二叉树「空结点后不能再有结点」的判断方法。
以下代码实现了二叉排序树的哪种操作?
01TreeNode* op(TreeNode* root, int val) { 02 if (root == nullptr) return new TreeNode(val); 03 if (val < root->val) { 04 root->left = op(root->left, val); 05 } else { 06 root->right = op(root->right, val); 07 } 08 return root; 09}
B:插入。root 为空时新建结点返回,val 小于根值递归插左子树、否则插右子树,并把结果挂回父结点,是 BST 的插入操作。
给定字符集 {A, B, C, D} 的出现频率分别为 {5, 1, 6, 2},则正确的哈夫曼编码是()。
B:合并 B1+D2=3、3+A5=8、8+C6=14,树为根(C, X)、X 左 M(10) 右 A(11)、M 下 B(100) D(101),左 0 右 1 得 C:0、A:11、B:100、D:101。
关于动态规划的描述,正确的是()。
B:动态规划要求最优子结构与重叠子问题两个性质;A 复杂度不一定总低于贪心,C 递归 DP 同样要存中间结果,D 子问题相互重叠而非互不重叠。
以下代码中,类的构造函数被调用了( )次。
01class MyClass { 02public: 03 MyClass() { 04 cout << "Constructor called!" << endl; 05 } 06}; 07int main() { 08 MyClass obj1; 09 MyClass obj2 = obj1; 10 return 0; 11}
A:1。obj1 定义时调用一次构造函数;obj2=obj1 是拷贝初始化,调用编译器生成的默认拷贝构造函数而非普通构造函数,故只输出 1 次。
以下代码实现了循环队列的哪种操作?
01class CircularQueue { 02 int* arr; 03 int front, rear, size; 04public: 05 CircularQueue(int k) { 06 size = k; 07 arr = new int[k]; 08 front = rear = -1; 09 } 10 bool enQueue(int value) { 11 if (isFull()) return false; 12 if (isEmpty()) front = 0; 13 rear = (rear + 1) % size; 14 arr[rear] = value; 15 return true; 16 } 17};
A:入队。enQueue 判满判空后把 rear 前移一位(取模回绕)并把 value 存入 arr[rear],是循环队列的入队操作。
以下代码用于统计二叉树的叶节点数量,请在横线处填入代码。
01int countLeafNodes(TreeNode* root) { 02 if (root == nullptr) return 0; 03 04 stack<TreeNode*> s; 05 s.push(root); 06 int count = 0; 07 while (!s.empty()) { 08 TreeNode* node = s.top(); 09 s.pop(); 10 11 if (node->left == nullptr && node->right == nullptr) { 12 count++; 13 } 14 15 if (node->right) s.push(node->right); 16 ____________ // 在此处填入代码 17 } 18 return count; 19}
A:遍历到非叶结点时,应把左孩子压栈继续检查,故填 if(node->left) s.push(node->left);配合已压入的右孩子完成整棵树遍历,统计叶结点数。
以下代码使用队列查找二叉树中的目标节点,请在横线处填入代码。
01TreeNode* findNode(TreeNode* root, int target) { 02 if (root == nullptr) return nullptr; 03 04 queue<TreeNode*> q; 05 q.push(root); 06 while (!q.empty()) { 07 TreeNode* current = q.front(); 08 q.pop(); 09 10 if (current->val == target) { 11 return current; // 找到目标节点 12 } 13 14 ____________ // 在此处填入代码 15 } 16 return nullptr; // 未找到目标节点 17}
A:BFS 查找目标,当前结点不匹配时把左右孩子依次入队继续逐层搜索;B、C 的 pop/front 不是入队操作,D 左右孩子入反了。
以下代码生成格雷编码,请在横线处填入代码。
01vector<string> generateGrayCode(int n) { 02 if (n == 0) return {"0"}; 03 if (n == 1) return {"0", "1"}; 04 05 vector<string> prev = generateGrayCode(n - 1); 06 vector<string> result; 07 08 for (string s : prev) { 09 result.push_back("0" + s); // 在前缀添加 0 10 } 11 for (int i = prev.size() - 1; i >= 0; i--) { 12 ____________ // 在此处填入代码 13 } 14 return result; 15}
A:格雷码迭代生成:先把上一代序列正序加前缀 0 加入结果,再倒序加前缀 1 追加,保证相邻编码只差一位,故填 push_back(1+prev[i])。
以下 背包代码中,横线处应填入的内容是()。
01int knapsack(int W, vector<int>& weights, vector<int>& values) { 02 int n = weights.size(); 03 vector<vector<int>> dp(n + 1, vector<int>(W + 1, 0)); 04 05 for (int i = 1; i <= n; i++) { 06 for (int j = 1; j <= W; j++) { 07 if (weights[i-1] > j) { 08 dp[i][j] = dp[i-1][j]; // 当前物品装不下 09 } else { 10 dp[i][j] = max(____________); // 在此处填入代码 11 } 12 } 13 } 14 return dp[n][W]; 15}
B:01 背包转移取「不放第 i 件 dp[i-1][j]」与「放入第 i 件 dp[i-1][j-weights[i-1]]+values[i-1]」的较大值;A 漏加价值,C、D 用错状态下标。
以下代码判断括号是否匹配,请在横线处填入代码。
01bool isBalanced(string s) { 02 stack<char> st; 03 for (char c : s) { 04 if (c == '(' || c == '[' || c == '{') { 05 st.push(c); 06 } else { 07 if (st.empty()) return false; // 无括号匹配 08 char top = st.top(); 09 st.pop(); 10 if ((c == ')' && top != '(') || 11 (c == ']' && top != '[') || 12 (c == '}' && top != '{')) { 13 return false; 14 } 15 } 16 } 17 return ____________; // 在此处填入代码 18}
C:全部字符处理完后,若栈空说明每个右括号都配到了左括号、且没有多余左括号,故返回 st.empty();返回 true/false 固定值无法反映栈中剩余括号。
关于下面代码,说法错误的是()。
01class Shape { 02protected: 03 string name; 04 05public: 06 Shape(const string& n) : name(n) {} 07 08 virtual double area() const { 09 return 0.0; 10 } 11}; 12 13class Circle : public Shape { 14private: 15 double radius; 16 17public: 18 Circle(const string& n, double r) : Shape(n), radius(r) {} 19 20 double area() const override { 21 return 3.14159 * radius * radius; 22 } 23}; 24 25class Rectangle : public Shape { 26private: 27 double width; // 宽度 28 double height; // 高度 29 30public: 31 Rectangle(const string& n, double w, double h) : Shape(n), width(w), height(h) {} 32 33 double area() const override { 34 return width * height; 35 } 36}; 37 38int main() { 39 Circle circle("MyCircle", 5.0); 40 Rectangle rectangle("MyRectangle", 4.0, 6.0); 41 42 Shape* shapePtr = &circle; 43 cout << "Area: " << shapePtr->area() << endl; 44 45 shapePtr = &rectangle; 46 cout << "Area: " << shapePtr->area() << endl; 47 48 return 0; 49}
A:错误项。派生类对象地址可以赋给基类指针(向上转型),shapePtr=&circle 与 shapePtr=&rectangle 都合法,不会编译错误;B、C、D 关于继承与多态的描述正确。
哈夫曼树在构造过程中,每次合并权值最小的两个节点,最终生成的树带权路径长度最小。
A:正确。哈夫曼算法每步贪心合并权值最小的两个结点,可以证明这种合并次序使最终生成的树带权路径长度(WPL)最小。,这正是贪心策略的体现。
格雷编码的相邻两个编码之间必须有多位不同,以避免数据传输错误。
B:错误。格雷码的定义恰相反:相邻两个编码之间只有一位不同,以此减少多位同时跳变造成的传输错误,而不是多位不同。,题述与定义相反。
在树的深度优先搜索(DFS)中,使用队列作为辅助数据结构以实现“先进后出”的访问顺序。
01void traverse(TreeNode* root) { 02 if (root == nullptr) return; 03 traverse(root->left); 04 cout << root->val << " "; 05 traverse(root->right); 06}
B:错误。DFS 需要先进后出地回溯,辅助结构是栈(或递归);队列实现先进先出,用于 BFS。附带的 traverse 函数是中序遍历递归,与队列无关。
以下代码实现的是一棵树的中序遍历:
TreeNode* root = new TreeNode{1};
root->left = new TreeNode{2};
root->right = new TreeNode{3};
root->left->left = new TreeNode{4};
A:正确。代码构建的树为 1(2(4),3),按中序遍历(先左子树、再根、后右子树)访问,顺序为 4 2 1 3,符合中序遍历定义。
C++ 支持构造函数重载,但默认无参数的构造函数只能有一个。
A:正确。构造函数可按参数列表重载多个,但无参构造函数只能有一个,否则创建对象调用无参构造时会产生二义性。,否则会二义性。
二叉排序树(BST)中,若某节点的左子树为空,则该节点一定是树中的最小值节点。
B:错误。左子树为空只说明该结点没有更小的后代,但整棵树的最左结点才是最小值;其他结点左子树为空时,树上仍可能有比它更小的值。
在动态规划解决一维硬币找零问题时,若硬币面额为 [1, 3, 4],目标金额为 ,则最少需要 枚硬币(3+3)。
A:正确。6=3+3 只需 2 枚硬币;1+1+4 需 3 枚、全用 1 元需 6 枚,均多于 2 枚,故最少硬币数为 2。
面向对象编程中,封装是指将数据和行为绑定在一起,并对外隐藏实现细节。
A:正确。封装把数据(成员变量)与操作(成员函数)绑定在类中,并通过访问权限对外隐藏实现细节,只暴露必要接口。,只暴露必要接口。
以下代码创建的树是一棵完全二叉树:
TreeNode* root = new TreeNode{1};
root->left = new TreeNode{2};
root->right = new TreeNode{3};
root->left->left = new TreeNode{4};
A:正确。树的层序为 1,2,3,4:前两层排满,第三层只有 4 且位于 2 的左孩子,结点从左到右连续,满足完全二叉树定义。
栈和队列均可以用双向链表实现,插入和删除操作的时间复杂度为 。
A:正确。双向链表在头、尾插入删除都是 O(1):栈用头插头删,队列队头出、队尾入,插入删除复杂度均为 O(1)。,均为 O(1) 操作。