Loading docs/lang/csl/sequence-container.md +43 −49 Original line number Diff line number Diff line Loading @@ -6,17 +6,15 @@ author: MingqiHuang, Xeonacid, greyqz, i-Yirannn ### 为什么要用 `vector` 作为 OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 `vector` 由于其较静态数组复杂很多的原因,时间效率在大部分情况下都要满慢于静态数组,所以在一般的正常存储数据的时候,我们是不选择 `vector` 的,下面给出几个 `vector` 优秀的特性,在需要用到这些特性的情况下, `vector` 能给我们带来很大的帮助。 作为 OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 `vector` 由于其较静态数组复杂很多的原因,时间效率在大部分情况下都要低于静态数组,所以在正常存储数据的时候,我们是不选择 `vector` 的,下面给出几个 `vector` 优秀的特性,在需要用到这些特性的情况下, `vector` 能给我们带来很大的帮助。 #### `vector` 重写了比较运算符 vector 以字典序为关键字重载了六个比较运算符,这使得我们可以方便的判断两个容器是否相等。(复杂度与容器大小成线性关系) #### `vector` 可以动态增长 #### `vector` 的内存是动态分配的 很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)我们知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要 `vector` 来把内存占用量控制在合适的范围内。 由于其动态分配的特性,所以在调用内存的常数上在很多情况下是要快于静态数组的。 #### `vector` 重写了比较运算符 很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)我们知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要 `vector` 来保证复杂度。 vector 以字典序为关键字重载了六个比较运算符,这使得我们可以方便的判断两个容器是否相等。(复杂度与容器大小成线性关系) #### `vector` 可以用赋值运算符来进行初始化 Loading @@ -24,45 +22,43 @@ vector 以字典序为关键字重载了六个比较运算符,这使得我们 ### `vector` 的构造函数 参见如下代码: 参见如下代码(假设你已经 `using` 了 `std::vector` , `std::cout` , `std::endl` , `std::copy` 与 `std::ostream_iterator` ): ```cpp void Vector_Constructor_Test() { // 1. 创建空vector v0; 常数复杂度 std::vector<int> v0; vector<int> v0; // 2. 创建一个初始空间为3的vector v1,其元素的默认值是0; 线性复杂度 std::vector<int> v1(3); vector<int> v1(3); // 3. 创建一个初始空间为5的vector v2,其元素的默认值是2; 线性复杂度 std::vector<int> v2(5, 2); vector<int> v2(5, 2); // 4. 创建一个初始空间为3的vector // v3,其元素的默认值是1,并且使用v2的空间配置器 线性复杂度 std::vector<int> v3(3, 1, v2.get_allocator()); vector<int> v3(3, 1, v2.get_allocator()); // 5. 创建一个v2的拷贝vector v4, 其内容元素和v2一样; 线性复杂度 std::vector<int> v4(v2); vector<int> v4(v2); // 6. 创建一个v4的拷贝vector v5,其内容是v4的[__First, __Last)区间 线性复杂度 std::vector<int> v5(v4.begin() + 1, v4.begin() + 3); vector<int> v5(v4.begin() + 1, v4.begin() + 3); // 以下是测试代码,有兴趣的同学可以自己编译运行一下本代码。 std::cout << "v1 = "; std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v2 = "; std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v3 = "; std::copy(v3.begin(), v3.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v4 = "; std::copy(v4.begin(), v4.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v5 = "; std::copy(v5.begin(), v5.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; cout << "v1 = "; copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v2 = "; copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v3 = "; copy(v3.begin(), v3.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v4 = "; copy(v4.begin(), v4.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v5 = "; copy(v5.begin(), v5.end(), ostream_iterator<int>(cout, " ")); cout << endl; // 移动v2到新创建的vector v6; std::vector<int> v6(move(v2)); std::cout << "v6 = "; std::copy(v6.begin(), v6.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; }; vector<int> v6(std::move(v2)); cout << "v6 = "; copy(v6.begin(), v6.end(), ostream_iterator<int>(cout, " ")); cout << endl; ``` 可以利用上述的方法构造一个 `vector` ,足够我们使用了。 Loading Loading @@ -129,7 +125,7 @@ vector 提供了如下几种迭代器 释放未使用的内存来减少内存使用。 此外,还有 `max_size()` , `reserve()` , `capacity()` 等 OIer 较少用到的函数,不做介绍。 此外,还有 `max_size()` , `reserve()` , `capacity()` 等 OIer 较少用到的函数,可自行查询。 ### `vector` 修改 Loading @@ -142,9 +138,7 @@ vector 提供了如下几种迭代器 ### `vector` 特化 `vector<bool>` 标准库提供对 `bool` 的 `vector` 优化,其空间占用与 `bitset` 一样,每个 `bool` 只占 1 bit,且支持动态内存。 注意, `vector<bool>` 没有 `bitset` 的位运算重载,所以适用情况与 `bitset` 并不完全重合,请选择食用。 标准库提供对 `bool` 的 `vector` 特化,每个“ `bool` ”只占 1 bit,且支持动态增长。但是其 `operator[]` 的返回值的类型不是 `bool&` 而是 `vector<bool>::reference` 。因此,请尽量避免使用 `vector<bool>` ,而是用 `deque<bool>` 或 `vector<char>` 替代。而如果你需要节省空间,请直接使用 `bitset` 。 ## deque Loading Loading
docs/lang/csl/sequence-container.md +43 −49 Original line number Diff line number Diff line Loading @@ -6,17 +6,15 @@ author: MingqiHuang, Xeonacid, greyqz, i-Yirannn ### 为什么要用 `vector` 作为 OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 `vector` 由于其较静态数组复杂很多的原因,时间效率在大部分情况下都要满慢于静态数组,所以在一般的正常存储数据的时候,我们是不选择 `vector` 的,下面给出几个 `vector` 优秀的特性,在需要用到这些特性的情况下, `vector` 能给我们带来很大的帮助。 作为 OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 `vector` 由于其较静态数组复杂很多的原因,时间效率在大部分情况下都要低于静态数组,所以在正常存储数据的时候,我们是不选择 `vector` 的,下面给出几个 `vector` 优秀的特性,在需要用到这些特性的情况下, `vector` 能给我们带来很大的帮助。 #### `vector` 重写了比较运算符 vector 以字典序为关键字重载了六个比较运算符,这使得我们可以方便的判断两个容器是否相等。(复杂度与容器大小成线性关系) #### `vector` 可以动态增长 #### `vector` 的内存是动态分配的 很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)我们知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要 `vector` 来把内存占用量控制在合适的范围内。 由于其动态分配的特性,所以在调用内存的常数上在很多情况下是要快于静态数组的。 #### `vector` 重写了比较运算符 很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)我们知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要 `vector` 来保证复杂度。 vector 以字典序为关键字重载了六个比较运算符,这使得我们可以方便的判断两个容器是否相等。(复杂度与容器大小成线性关系) #### `vector` 可以用赋值运算符来进行初始化 Loading @@ -24,45 +22,43 @@ vector 以字典序为关键字重载了六个比较运算符,这使得我们 ### `vector` 的构造函数 参见如下代码: 参见如下代码(假设你已经 `using` 了 `std::vector` , `std::cout` , `std::endl` , `std::copy` 与 `std::ostream_iterator` ): ```cpp void Vector_Constructor_Test() { // 1. 创建空vector v0; 常数复杂度 std::vector<int> v0; vector<int> v0; // 2. 创建一个初始空间为3的vector v1,其元素的默认值是0; 线性复杂度 std::vector<int> v1(3); vector<int> v1(3); // 3. 创建一个初始空间为5的vector v2,其元素的默认值是2; 线性复杂度 std::vector<int> v2(5, 2); vector<int> v2(5, 2); // 4. 创建一个初始空间为3的vector // v3,其元素的默认值是1,并且使用v2的空间配置器 线性复杂度 std::vector<int> v3(3, 1, v2.get_allocator()); vector<int> v3(3, 1, v2.get_allocator()); // 5. 创建一个v2的拷贝vector v4, 其内容元素和v2一样; 线性复杂度 std::vector<int> v4(v2); vector<int> v4(v2); // 6. 创建一个v4的拷贝vector v5,其内容是v4的[__First, __Last)区间 线性复杂度 std::vector<int> v5(v4.begin() + 1, v4.begin() + 3); vector<int> v5(v4.begin() + 1, v4.begin() + 3); // 以下是测试代码,有兴趣的同学可以自己编译运行一下本代码。 std::cout << "v1 = "; std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v2 = "; std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v3 = "; std::copy(v3.begin(), v3.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v4 = "; std::copy(v4.begin(), v4.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::cout << "v5 = "; std::copy(v5.begin(), v5.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; cout << "v1 = "; copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v2 = "; copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v3 = "; copy(v3.begin(), v3.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v4 = "; copy(v4.begin(), v4.end(), ostream_iterator<int>(cout, " ")); cout << endl; cout << "v5 = "; copy(v5.begin(), v5.end(), ostream_iterator<int>(cout, " ")); cout << endl; // 移动v2到新创建的vector v6; std::vector<int> v6(move(v2)); std::cout << "v6 = "; std::copy(v6.begin(), v6.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; }; vector<int> v6(std::move(v2)); cout << "v6 = "; copy(v6.begin(), v6.end(), ostream_iterator<int>(cout, " ")); cout << endl; ``` 可以利用上述的方法构造一个 `vector` ,足够我们使用了。 Loading Loading @@ -129,7 +125,7 @@ vector 提供了如下几种迭代器 释放未使用的内存来减少内存使用。 此外,还有 `max_size()` , `reserve()` , `capacity()` 等 OIer 较少用到的函数,不做介绍。 此外,还有 `max_size()` , `reserve()` , `capacity()` 等 OIer 较少用到的函数,可自行查询。 ### `vector` 修改 Loading @@ -142,9 +138,7 @@ vector 提供了如下几种迭代器 ### `vector` 特化 `vector<bool>` 标准库提供对 `bool` 的 `vector` 优化,其空间占用与 `bitset` 一样,每个 `bool` 只占 1 bit,且支持动态内存。 注意, `vector<bool>` 没有 `bitset` 的位运算重载,所以适用情况与 `bitset` 并不完全重合,请选择食用。 标准库提供对 `bool` 的 `vector` 特化,每个“ `bool` ”只占 1 bit,且支持动态增长。但是其 `operator[]` 的返回值的类型不是 `bool&` 而是 `vector<bool>::reference` 。因此,请尽量避免使用 `vector<bool>` ,而是用 `deque<bool>` 或 `vector<char>` 替代。而如果你需要节省空间,请直接使用 `bitset` 。 ## deque Loading