题目1:集合操作(MySet)
题目描述
实现一个简化的整数集合类MySet,该类持有一个unordered_set来存储元素,为了更方便地进行集合运算,要求通过操作符重载提供直观的集合运算接口。
具体要求
1. 操作符重载
(1)交集
- 交(
*):A * B返回集合A与集合B的交集 - 交赋值(
*=):A *= B即A = A * B
(2)并集与差集
- 并(
+):A + B返回集合A与集合B的并集 - 并赋值(
+=):A += B即A = A + B - 差(
-):A - B返回集合A与集合B的差集 - 差赋值(
-=):A -= B即A = A - B - 操作数类型支持
MySet或int(表示单个整数构成的集合),示例:
-
A + 1或1 + A→ 集合A与{1}的并集A - 1→ 集合A与{1}的差集1 - A→ 集合{1}与A的差集(结果为{1}或{})
2. 类型转换
bool():空集合返回false,非空集合返回trueint():返回集合的元素个数std::vector<int>():转换为向量,元素按升序排列
3. 输出流重载
- 友元函数:
friend std::ostream& operator<<(std::ostream& os, const MySet& s) - 输出格式:
{a0, a1, a2, ...}(元素按升序排列)
调用示例
#include "MySet.h"
int main() {
MySet A = {1, 2, 3, 4};
MySet B = {4, 5, 6, 7, 8};
std::cout << (A + 5) * B << std::endl;
B -= 8;
std::cout << A + (8 - B) << std::endl;
if (A * B) {
std::cout << "A size: " << static_cast<int>(A) << std::endl;
std::vector<int> a = static_cast<std::vector<int>>(A);
for (int i : a) {
std::cout << i << " ";
}
std::cout << std::endl;
}
}
输出结果
{4, 5}
{1, 2, 3, 4, 8}
A size: 4
1 2 3 4
提示
- 部分操作符可复用已实现的操作符简化代码
- 并集操作参考声明(其他操作可仿照):
MySet operator+(const MySet& other) const;
MySet operator+(int value) const;
friend MySet operator+(int value, const MySet& set);
MySet& operator+=(const MySet& other);
MySet& operator+=(int value);
- 需创建
MySet.h文件实现操作符重载,Main.cpp输入随意内容即可
代码模板(MySet.h)
#include <algorithm>
#include <iostream>
#include <unordered_set>
#include <vector>
class MySet {
private:
std::unordered_set<int> data;
public:
MySet() = default;
MySet(std::initializer_list<int> init) : data(init) {}
// ========== 基础方法 ==========
size_t size() const {
return data.size();
}
bool empty() const {
return data.empty();
}
bool contains(int value) const {
return data.find(value) != data.end();
}
void add(int value) {
data.insert(value);
}
void remove(int value) {
data.erase(value);
}
void clear() {
data.clear();
}
// ========== 操作符重载(待实现) ==========
// 交集
MySet operator*(const MySet& other) const;
MySet& operator*=(const MySet& other);
// 并集
MySet operator+(const MySet& other) const;
MySet operator+(int value) const;
friend MySet operator+(int value, const MySet& set);
MySet& operator+=(const MySet& other);
MySet& operator+=(int value);
// 差集
MySet operator-(const MySet& other) const;
MySet operator-(int value) const;
friend MySet operator-(int value, const MySet& set);
MySet& operator-=(const MySet& other);
MySet& operator-=(int value);
// 类型转换
operator bool() const {
return !empty();
}
operator int() const {
return static_cast<int>(size());
}
operator std::vector<int>() const {
std::vector<int> vec(data.begin(), data.end());
std::sort(vec.begin(), vec.end());
return vec;
}
// 输出流重载(友元)
friend std::ostream& operator<<(std::ostream& os, const MySet& s);
};
// ========== 操作符实现(待补充) ==========
MySet MySet::operator*(const MySet& other) const {
MySet res;
for (int val : data) {
if (other.contains(val)) {
res.add(val);
}
}
return res;
}
MySet& MySet::operator*=(const MySet& other) {
*this = *this * other;
return *this;
}
MySet MySet::operator+(const MySet& other) const {
MySet res;
for (int val : data) res.add(val);
for (int val : other.data) res.add(val);
return res;
}
MySet MySet::operator+(int value) const {
MySet res = *this;
res.add(value);
return res;
}
MySet operator+(int value, const MySet& set) {
return set + value;
}
MySet& MySet::operator+=(const MySet& other) {
*this = *this + other;
return *this;
}
MySet& MySet::operator+=(int value) {
*this = *this + value;
return *this;
}
MySet MySet::operator-(const MySet& other) const {
MySet res;
for (int val : data) {
if (!other.contains(val)) {
res.add(val);
}
}
return res;
}
MySet MySet::operator-(int value) const {
MySet res = *this;
res.remove(value);
return res;
}
MySet operator-(int value, const MySet& set) {
MySet res;
if (!set.contains(value)) {
res.add(value);
}
return res;
}
MySet& MySet::operator-=(const MySet& other) {
*this = *this - other;
return *this;
}
MySet& MySet::operator-=(int value) {
*this = *this - value;
return *this;
}
std::ostream& operator<<(std::ostream& os, const MySet& s) {
std::vector<int> vec = static_cast<std::vector<int>>(s);
os << "{";
for (size_t i = 0; i < vec.size(); ++i) {
if (i > 0) os << ", ";
os << vec[i];
}
os << "}";
return os;
}
题目2:通用环形缓冲区(RingBuffer)
题目描述
实现一个名为RingBuffer的C++类模板,代表固定大小的环形缓冲区(Circular Buffer)。环形缓冲区是高效的数据结构,用于在固定大小的存储空间中管理数据流。与普通队列不同,当缓冲区满时,新数据将自动覆盖最早的数据(First-In, Overwrite-Oldest)。
支持任意类型T的元素存储,需正确管理内部内存。
核心概念:环形覆盖
假设缓冲区容量为3:
push(1)→ buffer:[1, _, _]push(2)→ buffer:[1, 2, _]push(3)→ buffer:[1, 2, 3](满)push(4)→ buffer:[4, 2, 3](1被4覆盖,最早元素变为2)
功能要求
实现以下成员函数:
RingBuffer(size_t capacity):构造函数,分配存储capacity个T类型元素的空间~RingBuffer():析构函数,释放所有动态分配的内存void push(const T& value):添加元素
-
- 缓冲区未满:添加到队尾
- 缓冲区已满:覆盖队头元素,更新队头和队尾位置
void pop():移除队头元素(空缓冲区不执行操作)T& front():返回队头元素(最早加入)的引用T& back():返回队尾元素(最近加入)的引用size_t getSize() const:返回当前元素数量size_t getCapacity() const:返回总容量bool isFull() const:检查是否已满bool isEmpty() const:检查是否为空void print() const:按从旧到新顺序打印所有元素(空格分隔,末尾换行)
输入格式
每行一条操作指令,格式如下:
create <capacity>:创建容量为capacity的RingBuffer<int>对象push <value>:添加一个整数pop:移除最早元素front:打印队头元素back:打印队尾元素print:按顺序打印所有元素(队头到队尾)info:打印当前大小(Size)和容量(Capacity)
数据范围
- 缓冲区容量
capacity:0 <= capacity - 元素
value:int范围内
输出格式
front/back指令:输出对应数值;空缓冲区输出Emptyprint指令:一行输出所有元素(空格分隔);空缓冲区输出Emptyinfo指令:输出Size: <size>, Capacity: <capacity>
样例输入
create 3
push 10
push 20
info
push 30
info
print
push 40
info
print
front
back
pop
print
样例输出
Size: 2, Capacity: 3
Size: 3, Capacity: 3
10 20 30
Size: 3, Capacity: 3
20 30 40
20
40
30 40
样例解释
create 3:创建容量为3的缓冲区push 10、push 20:缓冲区为[10, 20],大小2push 30:缓冲区为[10, 20, 30],已满push 40:覆盖最早的10,逻辑缓冲区变为[20, 30, 40]pop:移除最早的20,缓冲区变为[30, 40]
代码模板
#include <iostream>
#include <vector>
#include <string>
template <typename T>
class RingBuffer {
private:
std::vector<T> data; // 底层存储
size_t head; // 队头索引(最早元素)
size_t tail; // 队尾索引(下一个插入位置)
size_t capacity; // 总容量
size_t currentSize; // 当前元素数量
public:
// 构造函数
RingBuffer(size_t cap) : capacity(cap), head(0), tail(0), currentSize(0) {
if (cap > 0) {
data.resize(cap);
}
}
// 析构函数
~RingBuffer() {
// vector自动管理内存,无需额外释放
}
// 添加元素(如果满则覆盖)
void push(const T& value) {
if (capacity == 0) {
return;
}
if (isFull()) {
// 覆盖队头,更新head
data[tail] = value;
head = (head + 1) % capacity;
} else {
// 插入队尾,增加大小
data[tail] = value;
currentSize++;
}
// 更新tail(循环索引)
tail = (tail + 1) % capacity;
}
// 移除队头元素
void pop() {
if (isEmpty()) {
return;
}
head = (head + 1) % capacity;
currentSize--;
}
// 获取队头引用
T& front() {
static T dummy;
return isEmpty() ? dummy : data[head];
}
// 获取队尾引用
T& back() {
static T dummy;
if (isEmpty()) {
return dummy;
}
// tail指向 next 插入位置,实际队尾是 tail-1(处理环绕)
size_t backIdx = (tail == 0) ? capacity - 1 : tail - 1;
return data[backIdx];
}
// 获取当前大小
size_t getSize() const {
return currentSize;
}
// 获取容量
size_t getCapacity() const {
return capacity;
}
// 检查是否已满
bool isFull() const {
return currentSize == capacity;
}
// 检查是否为空
bool isEmpty() const {
return currentSize == 0;
}
// 按从旧到新顺序打印元素
void print() const {
if (isEmpty()) {
std::cout << "Empty" << std::endl;
return;
}
size_t idx = head;
for (size_t i = 0; i < currentSize; ++i) {
if (i > 0) {
std::cout << " ";
}
std::cout << data[idx];
idx = (idx + 1) % capacity;
}
std::cout << std::endl;
}
};
int main() {
std::string command;
int capacity;
RingBuffer<int>* buffer = nullptr;
while (std::cin >> command) {
if (command == "create") {
std::cin >> capacity;
if (buffer) {
delete buffer;
}
buffer = new RingBuffer<int>(capacity);
} else if (command == "push") {
int value;
std::cin >> value;
if (buffer) {
buffer->push(value);
}
} else if (command == "pop") {
if (buffer) {
buffer->pop();
}
} else if (command == "front") {
if (buffer) {
if (buffer->isEmpty()) {
std::cout << "Empty" << std::endl;
} else {
std::cout << buffer->front() << std::endl;
}
}
} else if (command == "back") {
if (buffer) {
if (buffer->isEmpty()) {
std::cout << "Empty" << std::endl;
} else {
std::cout << buffer->back() << std::endl;
}
}
} else if (command == "print") {
if (buffer) {
buffer->print();
}
} else if (command == "info") {
if (buffer) {
std::cout << "Size: " << buffer->getSize()
<< ", Capacity: " << buffer->getCapacity() << std::endl;
}
}
}
if (buffer) {
delete buffer;
}
return 0;
}
解题思路与参考实现
题目1:RingBuffer
思路梳理
- 底层存储使用定长数组
T* data(容量为capacity)。 - 维护三个指标:
head指向队头(最旧元素),tail指向下一次写入位置,count为当前元素个数。 push:写入data[tail],若已满则先移动head覆盖最旧元素,否则递增count,最后tail = (tail + 1) % capacity。pop:空则无操作;否则head = (head + 1) % capacity并count--。front/back:front取data[head];back取(tail + capacity - 1) % capacity。- 判空判满:
count == 0/count == capacity;容量为 0 时所有操作直接返回以防越界。
参考代码
#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
// TODO: 将 RingBuffer 定义为模板类 template <typename T>
template <typename T>
class RingBuffer {
private:
// TODO: 添加私有成员变量
T* data;
size_t capacity;
size_t head;
size_t tail;
size_t count;
// 建议使用 T* data 或 std::vector<T> 作为底层存储
// 需要记录 head (队头), tail (队尾) 或 count (当前数量)
public:
// 构造函数
RingBuffer(size_t cap) : capacity(cap),head(0),tail(0),count(0){
// TODO
if (capacity>0) {
data = new T[capacity];
}else {
data = nullptr;
}
}
// 析构函数
~RingBuffer() {
// TODO
delete[] data;
data = nullptr;
}
// 添加元素 (如果满则覆盖)
void push(const T& value) {
// TODO
if (capacity == 0) {
return;
}
data[tail] = value;
if (isFull()) {
head = (head + 1) % capacity;
} else {
count++;
}
tail = (tail + 1) % capacity;
}
// 移除元素
void pop() {
// TODO
if (isEmpty()) {
return;
}
head = (head + 1) % capacity;
count--;
}
// 获取队头引用
T& front() {
// TODO
// 注意:实际项目中应处理空的情况,这里为了简单可假设调用前非空或返回默认值
return data[head];
}
// 获取队尾引用
T& back() {
// TODO
size_t tailReturn = (tail - 1 + capacity) % capacity;
return data[tailReturn];
}
size_t getSize() const {
// TODO
return count;
}
size_t getCapacity() const {
// TODO
return capacity;
}
bool isFull() const {
// TODO
if (count == capacity) {
return true;
}else {
return false;
}
}
bool isEmpty() const {
// TODO
if (count == 0) {
return true;
}else {
return false;
}
}
// 打印当前缓冲区的所有元素(从旧到新)
void print() const {
// TODO
if (isEmpty()) {
std::cout << "Empty" << std::endl;
return;
}
for (size_t i = 0; i < count; ++i) {
size_t idx = (head + i) % capacity;
if (i > 0) {
std::cout << " ";
}
std::cout << data[idx];
}
std::cout << std::endl;
}
};
int main() {
std::string command;
int capacity;
RingBuffer<int>* buffer = nullptr;
while (std::cin >> command) {
if (command == "create") {
std::cin >> capacity;
if (buffer) delete buffer;
buffer = new RingBuffer<int>(capacity);
} else if (command == "push") {
int value;
std::cin >> value;
if (buffer) buffer->push(value);
} else if (command == "pop") {
if (buffer) buffer->pop();
} else if (command == "front") {
if (buffer) {
if (buffer->isEmpty()) std::cout << "Empty" << std::endl;
else std::cout << buffer->front() << std::endl;
}
} else if (command == "back") {
if (buffer) {
if (buffer->isEmpty()) std::cout << "Empty" << std::endl;
else std::cout << buffer->back() << std::endl;
}
} else if (command == "print") {
if (buffer) {
if (buffer->isEmpty()) {
std::cout << "Empty" << std::endl;
} else {
buffer->print();
}
}
} else if (command == "info") {
if (buffer) {
std::cout << "Size: " << buffer->getSize()
<< ", Capacity: " << buffer->getCapacity() << std::endl;
}
}
}
if (buffer) delete buffer;
return 0;
}
代码解析
- 覆盖策略:
push时若满先前移head,保证最旧元素被替换;tail永远指向下一写位置。 - 取尾元素:
(tail + capacity - 1) % capacity处理循环减一。 - 安全性:容量为 0 时直接返回,避免除零或越界;析构释放底层数组。
题目2:MySet
思路梳理
- 内部使用
unordered_set<int>存储;通过基础操作add/contains/remove复用逻辑。 - 交并差:二元运算返回新集合,赋值运算在当前集合原地更新(可用临时容器后
swap)。 - 与
int的混合运算:将单个整数视为{value},提供对称友元实现前置写法(如1 + A)。 - 类型转换与输出:转换向量后排序,输出
{a0, a1, ...}升序保证稳定展示。
参考代码
#include <algorithm>
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;
class MySet {
private:
unordered_set<int> data;
public:
MySet() = default;
MySet(const initializer_list<int> init) : data(init) {}
// ========== 基础方法 ==========
size_t size() const {
return data.size();
}
bool empty() const {
return data.empty();
}
bool contains(const int value) const {
return data.find(value) != data.end();
}
void add(const int value) {
data.insert(value);
}
void remove(const int value) {
data.erase(value);
}
void clear() {
data.clear();
}
//交集
MySet operator*(const MySet& other) const;
MySet& operator*=(const MySet& other);
//并集
MySet operator+(const MySet& other) const;
MySet operator+(int value) const;
friend MySet operator+(int value, const MySet& set);
MySet& operator+=(const MySet& other);
MySet& operator+=(int value);
//差集
MySet operator-(const MySet& other) const;
MySet operator-(int value) const;
friend MySet operator-(int value, const MySet& set);
MySet& operator-=(const MySet& other);
MySet& operator-=(int value);
//类型转换
explicit operator bool() const;
explicit operator int() const;
explicit operator std::vector<int>() const;
//输出流重载
friend ostream& operator<<(ostream& os, const MySet& s);
};
//交集实现
inline MySet MySet::operator*(const MySet& other) const {
MySet result;
for (const int elem : data) {
if (other.contains(elem)) {
result.add(elem);
}
}
return result;
}
inline MySet& MySet::operator*=(const MySet& other) {
unordered_set<int> new_data;
for (int elem : data) {
if (other.contains(elem)) {
new_data.insert(elem);
}
}
data.swap(new_data);
return *this;
}
//并集实现
inline MySet MySet::operator+(const MySet& other) const {
MySet result = *this;
for (const int elem : other.data) {
result.add(elem);
}
return result;
}
inline MySet MySet::operator+(const int value) const {
MySet result = *this;
result.add(value);
return result;
}
inline MySet operator+(const int value, const MySet& set) {
return set + value;
}
inline MySet& MySet::operator+=(const MySet& other) {
for (const int elem : other.data) {
this->add(elem);
}
return *this;
}
inline MySet& MySet::operator+=(const int value) {
this->add(value);
return *this;
}
//差集实现
inline MySet MySet::operator-(const MySet& other) const {
MySet result;
for (const int elem : data) {
if (!other.contains(elem)) {
result.add(elem);
}
}
return result;
}
inline MySet MySet::operator-(const int value) const {
MySet result = *this;
result.remove(value);
return result;
}
inline MySet operator-(const int value, const MySet& set) {
MySet result;
if (!set.contains(value)) {
result.add(value);
}
return result;
}
inline MySet& MySet::operator-=(const MySet& other) {
unordered_set<int> new_data;
for (int elem : data) {
if (!other.contains(elem)) {
new_data.insert(elem);
}
}
data.swap(new_data);
return *this;
}
inline MySet& MySet::operator-=(const int value) {
this->remove(value);
return *this;
}
//类型转换
inline MySet::operator bool() const {
return !this->empty();
}
inline MySet::operator int() const {
return static_cast<int>(this->size());
}
inline MySet::operator vector<int>() const {
vector vec(this->data.begin(), this->data.end());
sort(vec.begin(), vec.end());
return vec;
}
//输出流
inline ostream& operator<<(ostream& os, const MySet& s) {
const auto vec = static_cast<vector<int>>(s);
os << "{";
for (size_t i = 0; i < vec.size(); ++i) {
if (i > 0) {
os << ", ";
}
os << vec[i];
}
os << "}";
return os;
}
代码解析
- 重载对称性:
int + MySet、int - MySet通过友元实现,确保单元素集合场景语义明确。 - 赋值类操作:使用临时
unordered_set后swap,避免边遍历边修改导致逻辑混乱。 - 输出与向量转换:统一排序后输出,保证展示顺序稳定、可读。
1万+

被折叠的 条评论
为什么被折叠?



