一、背景与目标
在性能敏感或内存控制要求高的场景下,标准库中的 deque 或 vector 未必最合适。实现一个自定义的循环数组结构,可以带来更大的灵活性与控制力。
二、CycleArray 类的功能设计
CycleArray<T> 是一个模板类,提供如下功能:
- 支持头尾插入与删除(双端队列)
- 自动扩容与缩容(动态数组)
- 支持访问首尾元素、判断是否空满
构造函数支持初始容量设定,内部以 unique_ptr<T[]> 管理资源。
三、实现关键与代码解析
1. 核心成员变量设计
std::unique_ptr<T[]> arr;
int start; // 闭区间,指向第一个有效元素
int end; // 开区间,指向可插入位置
int count; // 当前元素数量
int size; // 当前数组容量
2. 插入与删除逻辑
addFirst()
if (isFull()) resize(size * 2);
start = (start - 1 + size) % size;
arr[start] = val;
count++;
removeFirst()
arr[start] = T();
start = (start + 1) % size;
count--;
if (count > 0 && count == size / 4) resize(size / 2);
注:因为
start是闭区间,需要先操作再移动。
addLast() 与 removeLast() 同理
四、自动扩缩容逻辑
void resize(int newSize) {
std::unique_ptr<T[]> newArr = std::make_unique<T[]>(newSize);
for (int i = 0; i < count; ++i)
newArr[i] = arr[(start + i) % size];
arr = std::move(newArr);
start = 0;
end = count;
size = newSize;
}
- 使用取模操作保持循环特性;
- 复制时保持顺序不变;
- 设置新指针并更新容量信息。
五、示例与调试输出
CycleArray<int> q;
q.addLast(1);
q.addLast(2);
q.addFirst(0);
q.removeLast();
cout << q.getFirst(); // 输出 0
建议添加调试函数:
void print() const {
for (int i = 0; i < count; ++i)
std::cout << arr[(start + i) % size] << ' ';
std::cout << '\n';
}
六、设计哲学与易错点提示
区间设计:闭/开
| 指针 | 类型 | 行为 |
|---|---|---|
| start | 闭区间 | 指向当前第一个元素 |
| end | 开区间 | 指向插入尾部位置 |
易错点
removeFirst()顺序不能反;- 缩容要判断 count > 0,防止无限缩;
- 忘记使用
% size保证循环;
七、扩展建议
- 重载
operator[]实现下标访问; - 添加迭代器支持;
- 提供容量、索引边界检查接口;
- 可与
std::deque封装统一接口风格。
八、总结
CycleArray 是一个结构紧凑、逻辑严密的容器实现练习例子,特别适合面试或底层结构学习。理解其中的“闭开区间”策略、循环与扩缩容机制,将有助于写出更健壮的自定义容器代码。