C++ vector类型要点总结(以及各种algorithm算法函数)
概述
C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C++中,用容器向量(vector)实现。
容器向量也是一个类模板。vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,但是一个容器中的对象必须是同一种类型。简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
vector是一个类模板,不是一种数据类型。可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此vector <int >等都是数据类型。
vector对象初始化
vector 类定义了好几种构 造函数,用来定义和初始化 vector 对象。
初始化 vector 对象的方式
| 
 vector <T > v1 ;  | 
 vector 保存类型为 T 的对象。默认构造函数 v1 为空。  | 
| 
 vector < T > v2 ( v1 );  | 
 v2 是 v1 的一个副本。  | 
| 
 vector < T > v3 ( n , i );  | 
 v3 包含 n 个值为 i 的元素。  | 
| 
 vector < T > v4 ( n );  | 
 v4 含有值初始化的元素的 n 个副本。  | 
创建确定个数的元素
若要创建非空的 vector 对象,必须给出初始化元素的值。当把一个 vector 对象复制到另一个 vector 对象时,新复制的 vector 中每一个元素都初始化为原 vector 中相应元素的副本。但这两个 vector 对象必须保存同一种元素类型:
vector<int> ivec1; // ivec1 holds objects of type int
vector<int> ivec2(ivec1); // ok: copy elements of ivec1 into ivec2
vector<string> svec(ivec1); // error: svec holds strings, not ints
可以用元素个数和元素值对 vector 对象进行初始化。构造函数用元素个数来决定 vector 对象保存元素的个数,元素值指定每个元素的初始值:
vector<int> ivec4(10, -1); // 10 elements, each initialized to -1
vector<string> svec(10, "hi!"); // 10 strings, each initialized to "hi!"
值初始化
如果没有给出元素的初始化式,那么标准库将提供一个 值初始化的 ( value initialized )元素初始化式。这个由库生成的初始值用于初始化容器中的每个元素。而元素初始化式的值取决于存储在 vector 中元素的数据类型。
如果 vector 保存内置类型(如 int 类型) 的元素,那么标准库将用 0 值创建元素初始 化值:
vector<string> fvec(10); // 10 elements, each initialized to 0
如果向量保存类类型(如 string )的元素,标准库将用该类型的默认构造函数 创建 元素初始值:
vector<string> svec(10); // 10 elements, each an empty string
vector对象操作
vector 基本操作
| 
 v. empty()  | 
 如果 v 为空,则返回 true, 否则返回 false 。  | 
| 
 v . size ()  | 
 返回 v 中元素的个数。  | 
| 
 v . push _ back ( t )  | 
 在 v 的末尾增加一个值为 t 的元素。  | 
| 
 v [ n ]  | 
 返回 v 中位置为 n 的元素。  | 
| 
 v1 = v2  | 
 把 v1 的元素替换为 v2 中元素的副本。  | 
| 
 v1 == v2  | 
 如果 v1 与 v2 相等,则返回 true 。  | 
| 
 !=, <, <=, >, >=  | 
 保持这些操作符惯有的含义。  | 
vector 对象的 size
empty 和 size 操作类似于 string 类型的相关操作。成员函数 size 返回相应 vector 类定义的size_type 的值。
使用 size_type 类型时,必须指出该类型是在哪里定义的。 vector 类型总是 包括 vector 的元素类型:
vector<int>::size_type // ok
vector::size_type // error
向 vector 添加元素
push_back() 操作接受一个元素值,并将它作为一个新的元素添加到 vector 对象的后面,也就是“ 插入 ( push)” 到 vector 对象的 “ 后面 ( back ) ” :
- <span style="font-weight:normal;"><span style="font-size:14px;">// read words from the standard input and store them as elements in a vector
 - string word;
 - vector<string> text; // empty vector
 - while (cin >> word) {
 - text.push_back(word); // append word to text
 - }</span></span>
 
该循环从标准输入读取一系列 string 对象,逐一追加到 vector 对象的后面。首先定义一个空的 vector 对象 text 。每循环一次就添加一个新元素到 vector 对象,并将从 输入 读取的 word 值赋予该元素。当循环结束时, text 就包含了所有读入的元素。
vector 的下标操作(更推荐用迭代器)
vector 中的对象是没有命名的,可以按 vector 中对象的位置来访问它们。通常使用下标操作符来获取元素。 vector的下标操作类似于 string 类型的下标操作 ( 3 .2 .3 节 ) 。
vector 的下标操作符接受一个值,并返回 vector 中该对应位置的元素。 vector 元素的位置从 0 开始。下例使用 for循环把 vector 中的每个元素值都重置为 0 :
- <span style="font-weight:normal;"><span style="font-size:14px;">// reset the elements in the vector to zero
 - for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
 - ivec[ix] = 0;</span></span>
 
和 string 类型的下标操作符一样, vector 下标操作的结果为左值,因此可以像循环体中所做的那样实现写入。另外,和 string 对象的下标操作类似,这里用 size_type 类型作为 vector 下标的类型。
在上例中,即使 ivec 为空, for 循环也会正确执行。 ivec 为空则调用 size 返回 0 ,并且 for 中的测试比较 ix 和 0 。第一次循环时,由于 ix 本身就是 0 ,则条件测试失败, for 循环体一次也不执行。
仅能对确知已存在的元素进行下标操作
初学 C ++ 的程序员可能会认为 vector 的下标操作可以添加元素,其实不然:
- vector<int> ivec; // empty vector
 - for (vector<int>::size_type ix = 0; ix != 10; ++ix)
 - ivec[ix] = ix; <span style="color:#ff0000;"><strong>// disaster: ivec has no elements</strong></span>
 
上述程序试图在 ivec 中插入 10 个新元素,元素值依次为 0 到 9 的整数。但是,这里 ivec 是空的 vector 对象,而且下标只能用于获取已存在的元素。
这个循环的正确写法应该是:
- for (vector<int>::size_type ix = 0; ix != 10; ++ix)
 - ivec.push_back(ix); // ok: adds new element with value ix<span style="color:#000000;font-family:Arial;"> </span>
 
必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。
对于下标操作符 ( [] 操作符 ) 的使用有一点非常重要,就是仅能提取确实已存在的元素,例如:
- vector<int> ivec; // empty vector
 - cout << ivec[0]; // Error: ivec has no elements!
 - vector<int> ivec2(10); // vector with 10 elements
 - cout << ivec[10]; // Error: ivec has elements 0...9
 
试图获取不存在的元素必然产生运行时错误。和大多数同类错误一样,不能确保执行过程可以捕捉到这类错误,运行程序的结果是不确定的。由于取不存在的元素的结果是未定义的,因而不同的实现会导致不同的结果,但程序运行时几乎肯定会以某种有趣的方式失败。
本警告适用于任何使用下标操作的时候,如 string 类型的下标操作,以及将要简要介绍的内置数组的下标操作。
不幸的是,试图对不存在的元素进行下标操作是程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致 PC 机和其他应用中最常见的安全问题。
其他以及迭代器
① v.resize(2*v.size)或v.resize(2*v.size, 99) 将v的容量翻倍(并把新元素的值初始化为99)
②使用迭代器访问元素.
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;
③
- c.insert(pos,elem) // 在pos位置插入一个elem拷贝,传回新数据位置。
 - c.insert(pos,n,elem) // 在pos位置插入n个elem数据。无返回值。
 - c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。
 
vec.insert(vec.begin()+i,a);    在第i+1个元素前面插入a;
④
c.erase(pos) 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置。
⑤
c.assign(beg,end) 将[beg; end)区间中的数据赋值给c
c.assign(n,elem) 将n个elem的拷贝赋值给c。
⑥ c.at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
⑦c.back() 传回最后一个数据,不检查这个数据是否存在。
⑧ c.begin()传回迭代器中的第一个数据
c.clear()移除容器中所有数据。
c.empty()判断容器是否为空。
c.end()指向迭代器中末端元素的下一个,指向一个不存在元素。
其他更多参见百科:http://baike.baidu.com/link?url=L6vhhZKTvp6C62nPFPbYKnxbqXnRUTwt-2dV7e07ACU0CnFJ6kbyDbwQ-iPGqoY_
More:vector结构体
vector的元素不仅仅可以使int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。下面是一段简短的程序代码:
- #include<stdio.h>
 - #include<algorithm>
 - #include<vector>
 - #include<iostream>
 - using namespace std;
 - typedef struct rect
 - {
 - int id;
 - int length;
 - int width;
 - //对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
 - bool operator< (const rect &a) const
 - {
 - if(id!=a.id)
 - return id<a.id;
 - else
 - {
 - if(length!=a.length)
 - return length<a.length;
 - else
 - return width<a.width;
 - }
 - }
 - }Rect;
 - int main()
 - {
 - vector<Rect> vec;
 - Rect rect;
 - rect.id=1;
 - rect.length=2;
 - rect.width=3;
 - vec.push_back(rect);
 - vector<Rect>::iterator it=vec.begin();
 - cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;
 - return 0;
 - }
 
算法:
 #include<algorithm>中的泛函算法
搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if() 
分类排序:sort() 、merge() 
删除算法:unique() 、remove() 
生成和变异:generate() 、fill() 、transformation() 、copy() 
关系算法:equal() 、min() 、max() 
sort(v1.begin(),vi.begin()+v1.size/2); 对v1的前半段元素排序
list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到则返回被查内容第一次出现处指针,否则返回end()。
vector< typeName >::size_type x ; vector< typeName >类型的计数,可用于循环如同for(int i)
使用reverse将元素翻转
reverse(vec.begin(),vec.end());将元素翻转(在vector中,如果一个函数中需要两个迭代器,
一般后一个都不包含.)
使用sort排序
sort(vec.begin(),vec.end());(默认是按升序排列,即从小到大).
可以通过重写排序比较函数按照降序比较,如下:
定义排序比较函数:
- bool Comp(const int &a,const int &b)
 - {
 - return a>b;
 - }
 
调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。
- /*
 - vector 综合练习
 - Written by C_SuooL_Hu
 - 2013 10 29
 - */
 - #include <vector>
 - #include <string>
 - #include <iostream>
 - #include <algorithm>
 - using namespace std ;
 - int main()
 - {
 - // 四种初始化方式
 - vector<int> ivec_1;
 - vector<int> ivec_2(ivec_1);
 - vector<int> ivec_3(10, 0) ;
 - vector<int> ivec(10);
 - // 定义迭代器变量
 - vector<int>::iterator iter;
 - // 定义下标变量
 - vector<int>::size_type ix ;
 - system("echo off");
 - system("color 3") ;
 - // reset all the elements in ivec to 0
 - // 使用下标操作,重置为1
 - for (ix = 0; ix != ivec.size(); ++ix)
 - ivec[ix] = 1;
 - // print what we've got so far: should print 10 0's
 - cout << "使用下标赋值为1的vector<int>类型(同样用下标遍历输出):"<< endl;
 - for (ix = 0; ix != ivec.size(); ++ix)
 - cout << ivec[ix] << " ";
 - cout << endl;
 - // 使用迭代器的操作赋值,重置为0
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - *iter = 0;
 - // 遍历输出,使用迭代器
 - cout<<"使用迭代器赋值为0的vector<int>类型(同样用迭代器遍历输出):" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout<< endl ;
 - iter = ivec.begin();
 - while (iter != ivec.end())
 - {
 - *iter =2 ;
 - ++iter;
 - }
 - // 遍历输出,使用迭代器
 - cout<<"使用while循环的迭代器赋值为2的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout<< endl << endl ;
 - // 使用vector的成员函数操作vector<int>类型数据
 - // 添加元素
 - cout << "使用vector的成员函数操作vector<int>类型数据" << endl;
 - cout << "添加元素" << endl ;
 - cout << "使用迭代器,添加九个递增元素" << endl ;
 - for (ix = 0; ix != 10; ++ ix)
 - ivec.push_back(ix);
 - cout << "此时ivec共有" << ivec.size() << "个元素"<< endl;
 - // 遍历输出,使用迭代器
 - cout<<"使用下标增加元素为递增的的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout<< endl << endl;
 - // 插入元素
 - cout << "插入元素:在第二个位置插入一个43" << endl ;
 - ivec.insert(ivec.begin() + 1, 43); // 在2位置插入一个43拷贝,传回新数据位置。
 - // 遍历输出,使用迭代器
 - cout<<"使用迭代器遍历输出:" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout << "\n此时ivec共有" << ivec.size() << "个元素" ;
 - cout<< endl << endl ;
 - cout << "插入元素:在第一个位置插入三个13" << endl ;
 - ivec.insert(ivec.begin(), 3 , 13); // 在1位置插入3个13数据。无返回值。
 - // 遍历输出,使用迭代器
 - cout<<"使用迭代器遍历输出:" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout << "\n此时ivec共有" << ivec.size() << "个元素";
 - cout<< endl << endl ;
 - cout << "插入元素:在第7个位置插入ivec的[1, 6) 之间的数据:" << endl ;
 - ivec.insert(ivec.begin()+6, ivec.begin(), ivec.begin()+5); // 在7位置插入在[10,19)区间的数据。无返回
 - // 遍历输出,使用迭代器
 - cout<<"使用迭代器遍历输出:" << endl;
 - for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout << "\n此时ivec共有" << ivec.size() << "个元素";
 - cout<< endl << endl ;
 - cout << "使用assign赋值ivec_1(将ivec的第[10,19)个元素赋值给他):" <<endl ;
 - ivec_1.assign(ivec.begin()+9, ivec.begin()+18);
 - cout<<"使用迭代器遍历输出:" << endl;
 - for (iter = ivec_1.begin(); iter !=ivec_1.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout << "\n此时ivec_1共有" << ivec_1.size() << "个元素";
 - cout << endl;
 - cout << "使用assign赋值ivec_2:" <<endl ;
 - ivec_2.assign(10,8) ;
 - cout<<"使用迭代器遍历输出:" << endl;
 - for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
 - cout<< *iter << ' ' ;
 - cout << "\n此时ivec_2共有" << ivec_2.size() << "个元素";
 - cout << endl;
 - // 元素排序
 - /*
 - 由于vc 6.0对模板库支持不够好,这里的排序函数无法通过编译,但是使用vs2010编译通过。
 - cout << "对ivec排序:" << endl;
 - bool Comp(const int &a,const int &b)
 - {
 - return a>b;
 - }
 - sort (ivec.begin(), ivec.end,Comp);
 - cout<<"从大到小排序后,使用迭代器遍历输出:" << endl;
 - for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
 - cout<< *iter << ' ' ;
 - */
 - cout << "是否为空(0代表不是,1代表是):" << ivec.empty() << endl;
 - ivec.clear() ;
 - cout << "清空元素" << endl;
 - cout << "是否为空:" << ivec.empty() << endl;
 - return 0;
 - }
 
运行结果:
C++ vector类型要点总结(以及各种algorithm算法函数)的更多相关文章
- C++ vector类型要点总结
		
概述 C++内置的数组支持容器的机制,但是它不支持容器抽象的语义.要解决此问题我们自己实现这样的类.在标准C++中,用容器向量(vector)实现. 容器向量也是一个类模板.vector是C++标准模 ...
 - Spark DataFrame vector 类型存储到Hive表
		
1. 软件版本 软件 版本 Spark 1.6.0 Hive 1.2.1 2. 场景描述 在使用Spark时,有时需要存储DataFrame数据到Hive表中,一般的存储方式如下: // 注册临时表 ...
 - vector类型介绍
		
一.vector类型简介 标准库:集合或动态数组,我们可以放若干对象放在里面. vector他能把其他对象装进来,也被称为容器 #include <iostream> #include & ...
 - 【原创】【长期更新】【未完待续】自制vector类型
		
继<自制string类型>以来的第二篇自制类型的文章.马上要开学了,时间也不多了,争取在今年写完吧. 目录 一,vector类型简单介绍 1.简介 1.1.STL 1.2.vector 2 ...
 - C++ algorithm算法库
		
C++ algorithm算法库 Xun 标准模板库(STL)中定义了很多的常用算法,这些算法主要定义在<algorithm>中.编程时,只需要在文件中加入#include<algo ...
 - 03C++语言对C的增强——实用性、变量检测、struct类型、C++中所有变量和函数都必须有类型、bool类型、三目运算符
		
1.“实用性”增强 C语言中的变量都必须在作用域开始的位置定义,C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义. 2.C++对c语言register的增强 register关键字 ...
 - 《Algorithm算法》笔记:元素排序(2)——希尔排序
		
<Algorithm算法>笔记:元素排序(2)——希尔排序 Algorithm算法笔记元素排序2希尔排序 希尔排序思想 为什么是插入排序 h的确定方法 希尔排序的特点 代码 有关排序的介绍 ...
 - C++语言对C的增强(1)——实用性、变量检测、struct类型、C++中所有变量和函数都必须有类型、bool类型、三目运算符
		
1.“实用性”增强 C语言中的变量都必须在作用域开始的位置定义,C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义. 2.变量检测加强 在C语言中,重复定义多个同名的全局变量是合法的: ...
 - 孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数
		
孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 不同类型 ...
 
随机推荐
- Nginx 正向代理和反向代理
			
正向代理的概念 正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器这个代理服务器呢,他能访问那个我不能访问的网站于是我先连上代 ...
 - [转]JQuery 如何选择带有多个class的元素
			
比如下面代码需要选择同时带有这几个class的元素,怎么写? 1 <div class="modal fade in"></div> A: 1. 依次过滤 ...
 - js实现无刷新上传
			
在新增数据项的时候,用ajax实现无刷新提交,但上传文件的时候,由于数据类型原因,不能将页面的<asp:FileUpload>中以字符串值的方式传到js里调用.我一共找到了两个方法予以解决 ...
 - js获取指定小时日期格式化
			
不得不感叹一下,聪明的程序员写的代码真是让人惊奇 找了一圈格式化代码的方式,下面的这个使用了一个 slice 函数,真是厉害 https://stackoverflow.com/questions/4 ...
 - SQL GO语句
			
GO是批处理的标志,是一条或多条SQL语句的集合,SQL Server将批处理语句编译成一个可执行单元,此单元称为执行计划. GO语句把程序分成一个个代码块,即使一个代码块执行错误,它后面的代码块任然 ...
 - HTML5与CSS3设计模式 中文版 高清PDF扫描版
			
HTML5与CSS3设计模式是一部全面讲述用HTML5和CSS3设计网页的教程.书中含350个即时可用的模式 (HTML5和CSS3代码片段),直接复制粘贴即可使用,更可以组合起来构建出无穷的解决方案 ...
 - 零点起飞学HTML+CSS (顼宇峰) PDF扫描版
			
零点起飞学HTML+CSS系统地介绍了网站制作中各种常用的HTML标签和CSS属性,以及网站各个部分和各种布局的实现方法,还提供了大量实例来引导读者学习,力求让读者获得真正实用的知识.本书涉及面广,从 ...
 - 从零开始搭建.NET Core 2.0 API(学习笔记一)
			
从零开始搭建.NET Core 2.0 API(学习笔记一) 一. VS 2017 新建一个项目 选择ASP.NET Core Web应用程序,再选择Web API,选择ASP.NET Core 2. ...
 - 微信小程序小结(4) --  分包加载及小程序间跳转
			
分包加载 某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载(主要是空间不够用,哈哈~). 在构建小程序分包项目时,构建会输出一个或多个功能的分包,其中 ...
 - 51nod1478(yy)
			
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1478&judgeId=365133 题意: 中文题诶 ...