大一下学了STL,也翻了几遍书,vector在刷力扣题时更是每题都用。这次要自己实现一个vector,看清这个“最熟悉的陌生人”。
话不多说,我们直接开始。
首先分析实现需求:
设计一个名为 MyVector 的 Vector 类,该类应具备以下功能和特性:
1、基础成员函数:
- 构造函数:初始化 Vector 实例
- 析构函数:清理资源,确保无内存泄露
- 拷贝构造函数:允许通过现有的 MyVector 实例来创建一个新实例
- 拷贝赋值操作符:实现 MyVector 实例之间的赋值功能
2、核心功能:
- 添加元素到末尾:允许在 Vector 的末尾添加新元素
- 获取元素个数:返回 Vector 当前包含的元素数量
- 获取容量:返回 Vector 可以容纳的元素总数
- 访问指定索引处的元素:通过索引访问特定位置的元素
- 在指定位置插入元素:在 Vector 的特定位置插入一个新元素
- 删除数组末尾元素:移除 Vector 末尾的元素
- 清空数组:删除 Vector 中的所有元素,重置其状态
3、迭代与遍历:
- 使用迭代器遍历:实现迭代器以支持对 Vector 从开始位置到结束位置的遍历
- 遍历并打印数组元素:提供一个函数,通过迭代器遍历并打印出所有元素
4、高级特性:
- 容器扩容:当前容量不足以容纳更多元素时,自动扩展 Vector 的容量以存储更多元素
z这里面比较关键的就是vector的扩容机制,vector一般是成倍扩容,这里采用扩容两倍的实现思路。结合vector本身是动态数组的特性,其扩容函数可以实现如下:
void resize() {
int* newVecnum = new int[max_size * 2];
std::copy(vecnum, vecnum+temp_size, newVecnum);
delete vecnum;
vecnum = newVecnum;
max_size *= 2;
}
这里的copy区别于我们直接一个一个元素复制的原因在于它汇编代码实现的机制会更快一些。具体可以去看它对应的汇编代码。改天有空我们再写一篇博客来讲这个。
其他内容考虑到是动态数组,每次插入元素之前要确认是否达到最大长度,达到了就扩容,否则直接按照正常思维插入即可。
对应的输入描述:
题目的包含多行输入,第一行为正整数 N, 代表后续有 N 行命令序列。
接下来 N 行,每行包含一个命令,命令格式为 [operation] [parameters] ,具体命令如下:
push 命令:
- 格式:push [element]
- 功能:将 element 添加到 Vector 的末尾
size 命令:
get 命令:
- 格式:size
- 功能:返回 Vector 当前包含的元素数量
- 格式:get [index]
- 功能:返回 index 索引处的元素
insert 命令:
- 格式:insert [index] [element]
- 功能:在 Vector 的 index 索引处插入一个 element
pop 命令:
- 格式:pop
- 功能:移除 Vector 末尾的元素
clear 命令:
- 格式:clear
- 功能:删除 Vector 中的所有元素,重置其状态
print 命令:
- 格式:print
- 功能:提供一个函数,遍历并打印出所有元素
iterator 命令:
- 格式:iterator
- 功能:实现迭代器以支持对 Vector 从开始位置到结束位置的遍历
foreach 命令:
- 格式:foreach
- 功能:遍历并打印出所有元素
对应的输出描述:
题目包含 N 行输出,不同命令需要给出明确的反馈,输入格式如下:
push 命令:无输出
size 命令:输出一个整数,独占一行,代表当前 vector 中的元素数量
get 命令:输出一个整数,独占一行,如果索引有效,则输出指定索引处的元素,如果索引无效,则输出 -1
insert 命令:无输出
pop 命令:无输出
clear 命令:无输出
print 命令:按照顺序打印当前 vector 包含的所有元素,每个元素后都跟一个空格,打印结果独占一行;如果当前的 vector 为空,则打印 empty
iterator 命令:按照顺序打印当前 vector 包含的所有元素,每个元素后都跟一个空格,打印结果独占一行;如果当前的 vector 为空,则打印 empty
foreach 命令:按照顺序打印当前 vector 包含的所有元素,每个元素后都跟一个空格,打印结果独占一行;如果当前的 vector 为空,则打印 empty
具体代码如下:
#include <iostream>
#include <string>
class MyVector {
private:
int* vecnum;
int temp_size;
int max_size;
public:
MyVector(int size=1) {
vecnum = new int[size];
max_size = size;
temp_size = 0;
};
~MyVector() {
delete vecnum;
temp_size = max_size = 0;
};
MyVector(MyVector& mv) {
MyVector* anothermv = new MyVector();
*anothermv = mv;
}
MyVector& operator=(MyVector mv) {
this->vecnum = mv.vecnum;
this->temp_size = mv.temp_size;
this->max_size = mv.max_size;
return *this;
}
void resize() {
int* newVecnum = new int[max_size * 2];
std::copy(vecnum, vecnum+temp_size, newVecnum);
delete vecnum;
vecnum = newVecnum;
max_size *= 2;
}
int size() const { return temp_size; };
int capacity() const { return max_size; };
int get(int index) const {
if (index >= temp_size) return -1;
return vecnum[index];
}
void _push_back(int element) {
if (temp_size == max_size) resize();
vecnum[temp_size++] = element;
}
void insert(int index, int element) {
if (temp_size == max_size) resize();
if (index > temp_size) return;
for (int i = temp_size + 1; i > index; i--) {
vecnum[i] = vecnum[i - 1];
}
vecnum[index] = element;
temp_size++;
}
void pop() {
if (temp_size > 0)
temp_size--;
}
void clear() {
temp_size = 0;
}
void print() {
if (temp_size == 0) {
std::cout << "empty" << std::endl;
return;
}
for (int i = 0; i < temp_size; i++) std::cout << vecnum[i] << ' ';
std::cout << std::endl;
}
int* begin() const {
return vecnum;
}
int* end() const {
return vecnum + temp_size;
}
};
int main() {
int n;
std::cin >> n;
MyVector myvec;
while (n--) {
std::string s;
std::cin >> s;
int index = 0, element = 0;
if (s == "push") {
std::cin >> element;
myvec._push_back(element);
}
if (s == "size"){
std::cout << myvec.size() << std::endl;
}
if (s == "get") {
std::cin >> index;
std::cout << myvec.get(index) << std::endl;
}
if (s== "insert") {
std::cin >> index >> element;
myvec.insert(index, element);
}
if (s == "pop") {
myvec.pop();
}
if (s == "clear") {
myvec.clear();
}
if (s == "print") {
myvec.print();
}
if (s == "iterator") {
if (myvec.size() == 0) {
std::cout << "empty" << std::endl;
continue;
}
for (int* it = myvec.begin(); it != myvec.end(); it++) {
std::cout << *(it) << ' ';
}
std::cout << std::endl;
}
if (s == "foreach") {
myvec.print();
}
}
}
给出的可运行的输入输出示例如下:
输入:
15
push 20
push 30
push 40
insert 0 10
size
get 1
pop
iterator
foreach
clear
size
20 30 40
4
10 20 30 40
20
10 20 30
10 20 30
10 20 30
0
empty