标准模板库(STL)使用---vector
2015-09-10 10:02
232 查看
或许你已经把 C++ 作为主要的编程语言用来解决 TopCoder 上的问题。这意味着你已经简单使用过了 STL,因为数组和字符串都是作为 STL 对象传递给函数。也许你已经注意到了,很多程序员写代码比你快得多,也更简洁。
或许你还不是但想成为一名 C++ 程序猿,因为这种编程语言功能很强大还有丰富的库(也许是因为在 TopCoder 的练习室里和竞赛中看到了很多非常精简的解决方案)。
无论过去如何,这篇文章都会有所帮助。在这里,我们将回顾标准模板库(Standard Template Library—STL,一个非常有用的工具,有时甚至能在算法竞赛中为你节省大量时间)的一些强大特性。
要熟悉 STL,最简单的方式就是从容器开始。
容器
无论何时需要操作大量元素,都会用到某种容器。C语言只有一种内置容器:数组。
问题不在于数组有局限性(例如,不可能在运行时确定数组大小)。相反,问题主要在于很多任务需要功能更强大的容器。
例如,我们可能需要一个或多个下列操作:
当然,我们可以在一个普通数组上实现这些功能。但是,这些琐碎的实现会非常低效。你可以创建树结构或哈希结构来快速解决问题,但是想想:这种容器的实现是取决于即将存储的元素类型吗?例如,我们要存储平面上的点而不是字符串的话,是不是要重写这个模块才能实现功能?
如果不是,那我们可以一劳永逸地为这种容器开发出接口,然后对任何数据类型都能使用。简言之,这就是 STL 容器的思想。
前言
程序要使用 STL 时,应包含(#include)适当的标准头文件。对大部分容器来说,标准头文件的名称和容器名一致,且不需扩展名。比如说,如果你要用栈(stack),只要在程序最开头添加下面这行代码:
容器类型(还有算法、运算符和所有STL也一样)并不是定义在全局命名空间,而是定义在一个叫“std”的特殊命名空间里。在包含完所有头文件之后,写代码之前添加下面这一行:
还有另一个很重要的事情要记住:容器类型也是模板参数。在代码中用“尖括号”(‘<’/’>’)指明模板参数。比如:
如果要进行嵌套式的构造,确保“方括号”之间不是紧挨着——留出一个空格的位置。(译者:C++11新特性支持两个尖括号之间紧挨着,不再需要加空格)
一、Vector
最简单的 STL 容器就是 vector。Vector 只是一个拥有扩展功能的数组。顺便说一下,vector 是唯一向后兼容 C 代码的容器——这意味着 vector 实际上就是数组,只是拥有一些额外特性。
Vector 最常使用的特性就是获取容器大小
有两点要注意:首先,size() 函数返回的值是无符号的,这点有时会引起一些问题。其次,如果你想知道容器是否为空,把 vector 的 size() 返回值和0比较不是一个好的做法。你最好使用 empty() 函数.
另一个 vector 中经常使用的函数是 push_back。push_back 函数向 vector 尾部添加一个元素,容器长度加 1。思考下面这个例子:
别担心内存分配问题——vector 不会一次只分配一个元素的空间。相反,每次用 push_back 添加新元素时,vector 分配的内存空间总是比它实际需要的更多。你应该担心的唯一一件事情是内存使用情况。
当你需要重新改变 vector 的大小时,使用 resize() 函数:
Resize() 函数让 vector 只存储所需个数的元素。如果你需要的元素个数少于 vector 当前存储的个数,剩余那些元素就会被删除。如果你要求 vector 变大,使用这个函数也会扩大它的长度,并用 0 填充新创建的元素。
注意,如果在使用了 resize() 后又用了 push_back(),那新添加的元素就会位于新分配内存的后面,而不是被放入新分配的内存当中。上面的例子得到的 vector 大小是25,如果在第二个循环中使用 push_back(),那vector 的大小最后会是30。
结果:
使用 clear() 函数来清空 vector。这个函数使 vector 包含 0 个元素。它并不是让所有元素的值为0——注意——它是完全删除所有元素,成为空容器。
向 vector 添加数据的最简单方式是使用 push_back()。但是,万一我们想在除了尾部以外的地方添加数据呢?Insert() 函数可以实现这个目的。同时还有 erase() 函数来删除元素。但我们得先讲讲迭代器。
你还应该记住另一个非常重要的事情:当 vector 作为参数传给某个函数时,实际上是复制了这个 vector(也就是值传递)。在不需要这么做的时候创建新的 vector 可能会消耗大量时间和内存。实际上,很难找到一个任务需要在传递 vector 为参数时对其进行复制。因此,永远不要这么写:
相反,使用下面的构造方法(引用传递):
如果在函数里要改变 vector 中的元素值,那就去掉‘const’修饰符。
或许你还不是但想成为一名 C++ 程序猿,因为这种编程语言功能很强大还有丰富的库(也许是因为在 TopCoder 的练习室里和竞赛中看到了很多非常精简的解决方案)。
无论过去如何,这篇文章都会有所帮助。在这里,我们将回顾标准模板库(Standard Template Library—STL,一个非常有用的工具,有时甚至能在算法竞赛中为你节省大量时间)的一些强大特性。
要熟悉 STL,最简单的方式就是从容器开始。
容器
无论何时需要操作大量元素,都会用到某种容器。C语言只有一种内置容器:数组。
问题不在于数组有局限性(例如,不可能在运行时确定数组大小)。相反,问题主要在于很多任务需要功能更强大的容器。
例如,我们可能需要一个或多个下列操作:
向容器添加某种字符串 从容器中移除一个字符串 确定容器中是否存在某个字符串 从容器中返回一些互不相同的元素 对容器进行循环遍历,以某种顺序获取一个附加字符串列表。
当然,我们可以在一个普通数组上实现这些功能。但是,这些琐碎的实现会非常低效。你可以创建树结构或哈希结构来快速解决问题,但是想想:这种容器的实现是取决于即将存储的元素类型吗?例如,我们要存储平面上的点而不是字符串的话,是不是要重写这个模块才能实现功能?
如果不是,那我们可以一劳永逸地为这种容器开发出接口,然后对任何数据类型都能使用。简言之,这就是 STL 容器的思想。
前言
程序要使用 STL 时,应包含(#include)适当的标准头文件。对大部分容器来说,标准头文件的名称和容器名一致,且不需扩展名。比如说,如果你要用栈(stack),只要在程序最开头添加下面这行代码:
#include<stack>
容器类型(还有算法、运算符和所有STL也一样)并不是定义在全局命名空间,而是定义在一个叫“std”的特殊命名空间里。在包含完所有头文件之后,写代码之前添加下面这一行:
using namespace std;
还有另一个很重要的事情要记住:容器类型也是模板参数。在代码中用“尖括号”(‘<’/’>’)指明模板参数。比如:
vector<int> N;
如果要进行嵌套式的构造,确保“方括号”之间不是紧挨着——留出一个空格的位置。(译者:C++11新特性支持两个尖括号之间紧挨着,不再需要加空格)
vector<vector<int> > CorrectDefinition; vector<vector<int>> WrongDefinition; //Wrong: compiler may be confused by 'operator >>'
一、Vector
最简单的 STL 容器就是 vector。Vector 只是一个拥有扩展功能的数组。顺便说一下,vector 是唯一向后兼容 C 代码的容器——这意味着 vector 实际上就是数组,只是拥有一些额外特性。
vector<int> v(10); //把’v’声明成一个存放了 10 个 vector<int> 类型元素的数组,初始化为空 //实际上,当你敲下vector<int> v就创建了一个空 vector for(int i = 0; i < 10; i++) { v[i] = (i+1)*(i+1); cout<<v[i]<<endl; } for(int i = 9; i > 0; i--) { v[i] -= v[i-1]; }
Vector 最常使用的特性就是获取容器大小
int elements_count = v.size()
有两点要注意:首先,size() 函数返回的值是无符号的,这点有时会引起一些问题。其次,如果你想知道容器是否为空,把 vector 的 size() 返回值和0比较不是一个好的做法。你最好使用 empty() 函数.
另一个 vector 中经常使用的函数是 push_back。push_back 函数向 vector 尾部添加一个元素,容器长度加 1。思考下面这个例子:
vector<int> v1; for(int i=1; i<10; i *= 2) { v1.push_back(i);//添加 } for(unsigned int i=0; i<v1.size(); i++) { cout<<v1[i]<<endl;//输出 }
别担心内存分配问题——vector 不会一次只分配一个元素的空间。相反,每次用 push_back 添加新元素时,vector 分配的内存空间总是比它实际需要的更多。你应该担心的唯一一件事情是内存使用情况。
当你需要重新改变 vector 的大小时,使用 resize() 函数:
vector<int> v(20); for(int i=0; i<20; i++) { v[i]=i+1; } v.resize(25);//重新改变 vector 的大小 for(int i=20; i<25; i++) { v[i] = i*2; }
Resize() 函数让 vector 只存储所需个数的元素。如果你需要的元素个数少于 vector 当前存储的个数,剩余那些元素就会被删除。如果你要求 vector 变大,使用这个函数也会扩大它的长度,并用 0 填充新创建的元素。
注意,如果在使用了 resize() 后又用了 push_back(),那新添加的元素就会位于新分配内存的后面,而不是被放入新分配的内存当中。上面的例子得到的 vector 大小是25,如果在第二个循环中使用 push_back(),那vector 的大小最后会是30。
int main() { vector<int> v(20); for(int i=0; i<20; i++) { v[i]=i+1; } v.resize(25); ///////////// for(int i=20; i<25; i++) { v.push_back(i);///////////////// } for(unsigned int i=0; i<v.size(); i++) { cout<<v[i]<<" "; } cout<<endl<<v.size()<<endl; return 0; }
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0 0 0 0 0 20 21 22 23 24 30 //大小变为30
使用 clear() 函数来清空 vector。这个函数使 vector 包含 0 个元素。它并不是让所有元素的值为0——注意——它是完全删除所有元素,成为空容器。
向 vector 添加数据的最简单方式是使用 push_back()。但是,万一我们想在除了尾部以外的地方添加数据呢?Insert() 函数可以实现这个目的。同时还有 erase() 函数来删除元素。但我们得先讲讲迭代器。
你还应该记住另一个非常重要的事情:当 vector 作为参数传给某个函数时,实际上是复制了这个 vector(也就是值传递)。在不需要这么做的时候创建新的 vector 可能会消耗大量时间和内存。实际上,很难找到一个任务需要在传递 vector 为参数时对其进行复制。因此,永远不要这么写:
void some_function(vector<int> v) // { //Never do it unless you’re sure what you do! }
相反,使用下面的构造方法(引用传递):
void some_function(const vector<int> &v) //!!!!!! { //OK//... }
如果在函数里要改变 vector 中的元素值,那就去掉‘const’修饰符。
int modify_vector(vector<int> &v) { //Correct V[0]++; }
相关文章推荐
- 浅析STL中的常用算法
- STL区间成员函数及区间算法总结
- c++ STL容器总结之:vertor与list的应用
- C++在成员函数中使用STL的find_if函数实例
- 关于STL中list容器的一些总结
- 关于STL中的map容器的一些总结
- 浅析stl序列容器(map和set)的仿函数排序
- STL list链表的用法详细解析
- stl容器set,map,vector之erase用法与返回值详细解析
- STl中的排序算法详细解析
- 关于STL中vector容器的一些总结
- 关于STL中set容器的一些总结
- 简单说说STL的内存管理
- CppUtest发现的STL容器内存泄漏问题
- STL中算法
- STL简单应用
- vector-list-deque
- 三十分钟掌握STL
- 1.sort()
- 刚刚接触到一个STL的函数make_pair()