- 使用vector必须加上头文件
#include <vector>
- vector表示一个类型相同的对象的集合,如:
vector <int> I;
vector <string> s;
vector <类名> D;
- c++中既有类模板,也有函数模板,模板本身不是一个类或者函数,更像是一份说明,编译器根据模板创建一个类或者模板的过程称为实例化。vector是一个类模板。对于类模板需要提供额外的信息指定模板到底生成什么样的类,实例化提供的信息:模板名后跟一对尖括号,括号内即为信息。
- vector可以包含的内容,除了引用类型,大部分都可。
- 针对vector的对象类型是vector,
vector<vector<int> >//有空格,老式写法
vector<vector<int>>//无空格,c++11写法
- 定义和初始化:
最常见的方式是定义一个空的vector,运行时再根据需要添加。v1。
vector<T> v1;
vector<T> v2(v1);
vector<T> v2=v1;
vector<T> v3(n,val)//n个重复的元素,元素值为val;
vector<T> v4(n);//n个;
vector<T> v5{a,b,c};//区分列表初始化
vector<T> v5={a,b,c};//
vector<T> v6{"a","b","c"};//列表初始化
- 区分列表初始值还是元素:
vector<int> v1(10);//10个元素,每个初始化为0
vector<int> v2{10};//1个元素,为10
vector<int> v3(10,1);//10个元素,每个值为1
vector<int> v4{10,1};//2个元素,值为10,1
vector<string> s1{"hi"};//列表初始化
vector<string> s2("hi");//错误,不能使用字符串字面值构建vector对象
vector<string> s3{10};//10个元素,每个都是默认初始化的值
vector<string> s4{10,"hi"};//10个值,每个值为hi
- 向vector中添加对象:
直接初始化不常用,更常用的是定义时为空,要用时往里添加值;
使用函数push_back()。如:
vector<int> I;
for(i=0;i<100;++i)
I.push_back(i);//
string s;
vector <string> v;
while(cin>>s)
v.push_back(s);
- 如在循环体内部包含有向vector添加元素的语句,如上的while循环,则不能使用范围for
- vector的一些函数:v.size()、v.empty()、v.push_back()、v[n](返回v中第n个位置上的引用。
- 访问vector中的元素:与string类似
vector<int> v{1,2,3,4,5,6};
for(auto &i:v)//范围for循环,改变值,则用引用
i*=i;
for(auto i:v)//范围for循环,只输出,
cout<<i<<" ";
cout<<endl;
for(decltype(v.size()) i=0;i<v.size();++i)
cout<<v[i]<<"_";
cout<<endl;
一种通过范围for循环,一种通过下标索引。
注意:绝对不能通过下标形式来添加vector元素。
string对象也不能通过下标形式进行添加元素,可能用于访问。
- 溢出现象:
只能对 确知已存在的元素执行下标操作。
vector<int> v;
cout<<v[0];/错误,v没有初始化,并不知道有没有值,不能通过下标访问
vector<int> v1(10);
cout<<v1[10];//错误,v的合法范围是0-9,
-
迭代器
1)迭代器提供了对对象的间接访问
2)所有的容器包括vector都有迭代器,但是只有vector既支持迭代器,也可以使用下表运算。string不是容器,但也支持迭代器和下标。
3)有迭代器的类型同时拥有返回迭代器的成员,比如,begin 和 end成员。
4)begin返回指向第一个元素的迭代器,end返回指向最后一个元素下一个位置的迭代器。如果容器为空,则begin 和 end 返回的是同一位置,可通过此来判断容器是否为空。 -
迭代器的运算:
1)*iter 解引用,来获取该迭代器指示的元素。注:执行解引用的迭代器必须合法并确实指向某一元素。解引非法的迭代器和尾后迭代器是未定义的行为。
2)++iter/–iter 自加自减,令iter指示容器中的下一个/上一个元素。
3)== != 判断相等或者不等
4)iter+n/iter-n n为整数,加减一个整数结果仍未一个迭代器,指向的位置变了n
5)iter-iter1 两个迭代器相减的结果是他们的距离,结果的类型是difference_type带符号整数型,参与运算的迭代器必须是指向同一容器的元素
string s("some string");
if(s.begin()!=s.end())//确保s非空
auto it =s.begin();//it是指向第一个元素的迭代器。
*it =toupper(*it);//通过操作解引的迭代器让第一个元素变为大写形式
- 迭代器的类型
iterator 和 const_iterator
vector <int>::iterator it;//it能读写vextor中的元素
vector <int>::const_iterator it1;//it1只能读,不能写
begin()和end()运算符返回的类型:由对象是否是常量决定
1)如果对象是常量,则返回const_iterator,如果不是常量则返回iterator
2)c++11新引进的cbegin() 和cend()新函数,方便返回const_iterator
vector <int> v1;
const vector <int> v2;
auto it1 = v1.begin();//it1的类型是iterator
auto it2 = v2.begin();//it2的类型是const_iterator
- 简单的运用
1)如检查一个字符串组成的容器是否为空
vector <string> v1;//此时定义的是空的,但这里只是示意有这么一个容器。
it = v1.begin();//此时的it是指向第一个元素的迭代器,但也只是示意其是v1的迭代器
(*it).enpty();//通过解引,调用结果对象的empty成员。
为简化使用箭头运算符-> ,即it->empty()与(*it).empty()一样
-
迭代器失效:
1)不能在范围for循环中向vector对象中添加对象,
2)任何一种改变容器 容量的操作,如添加元素.push_back(),会使该对象的迭代器失效 -
二分法
在有序列中使用的方法
auto beg = text.begin();
auto end = text.end();
auto mid = text.begin() + (end-beg)/2;
while(mid!=end && mid!= sought)//当还有元素未被检查且还没有找到目标值sought时
if(*mid>sought)
end = mid;
else
beg = mid+1;
mid = beg + (end-beg)/2;//重置一下mid