顺序容器为程序员提供了控制元素储存和访问顺序的能力,这种顺序不依赖与元素的值,而是与元素加入容器时的位置相对应。
所有顺序容器都提供了快速顺序访问元素的能力。
1.顺序容器概述
顺序容器有:vector;deque;list;forward_list;array;string.
1.1 vector
可变大小数组,支持快速随机访问,在尾部之外的位置插入或者删除元素会很慢。
1.2 deque
双端队列,支持快速随机访问。在头尾位置插入删除速度很快。
1.3 list
双向链表,只支持双向顺序访问,在list中任何位置插入删除操作都很快。
1.4 forward_list
单向链表,只支持单向顺序访问,在链表中任何位置插入删除操作都很快
1.5 array
固定大小的数组。支持快速随机访问。不能添加删除元素。
1.6 string
用于保存字符,随机访问快,在尾部插入删除速度快。
标准库类型vector;deque;list;forward_list;array;表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象,因为vector;deque;list;forward_list;array;容纳着其他对象,所以常称为“容器”。
使用vector;deque;list;forward_list;array;类型必须首先包含vector;deque;list;forward_list;array;头文件。
vector;deque;list;forward_list;array;的定义在命名空间std中。
c++语言既有类模板也有函数模板,其中vector;deque;list;forward_list;array;是一个类模板。模板本身不是类和函数,相反可以将模板看作为编译器生成类或者函数编写的一份说明,编译器根据模板创建类或者函数的过程称为实例化,当使用模板类时,需要指出编译器应把类或者函数实例化成何种类型。
2.初始化
2.1 vector;deque;list;forward_list;
array初始化:array<int,10> a;
container<int> a1; 默认初始化
container<int> a2 = {1,2,3,4};列表初始化
container<int> a3(a2);拷贝初始化
container<int> a4=a3;拷贝初始化
container<int> a5(5, 1);值初始化
container<int> a6{1,2,3,4};列表初始化
container<int> a7(a6.begin(),a6.end());(不适用于array)
container<int> a8(a6.begin()+1,a6.end()-1);(不适用于array)
container<int> a9(&a6[0],&a6[4]);(不适用于array)
2.2 string
string a1; 默认初始化,a1是个空字符串;
string a2 = "hello";拷贝初始化,a2是字面值hello的一个副本
string a3(a2);拷贝初始化,a3是字面值a2的一个副本
string a4=a3;拷贝初始化,a4是字面值a3的一个副本
string a5(5, '1');直接初始化,a5="11111"
string a6("hello5");直接初始化
string a7(a6.begin(),a6.end());直接初始化
string a8(a6.begin()+1,a6.end()-1);直接初始化
string a9(&a6[0],&a6[4]);直接初始化
3.操作
3.1 begin和end;cbegin和cend;rbegin和rend;crbegin和crend;
c.begin(),c.end()返回指向c的首元素和尾元素之后位置的迭代器。
c.cbegin(),c.cend()返回const_iterator
c.rbegin(),c.rend()返回c的尾元素和首元素之前位置的迭代器(不支持forward_list)
c.crbegin(),c.crend()返回const_reverse_iterator(不支持forward_list)
list<int> b = { 1,2,3 };
list<int>::iterator i1 = b.begin();
list<int>::iterator i2 = b.end();
for (auto i = i1; i != i2; i++)
cout << *i;
cout << endl; 123
list<int>::reverse_iterator i4 = b.rbegin();
list<int>::reverse_iterator i3 = b.rend();
for (auto i = i4; i != i3;i++)
cout << *i ;
cout << endl; 321
3.2 swap和assign
list<int> a,b ;
swap(a,b),a.swap(b)交换a,b中的元素,比a=b快
assign不适用于array
a.assign(b)将a中元素替换为b中的元素,
a.assign(m,n)将a中元素替换为迭代器m,n中的元素,迭代器m,n不能指向a
3.3 push_front,push_back和insert
array都不支持
push_front将元素插入到头部,list,forward_list,deque支持
push_back将元素插入到尾部,list,vector,string,deque支持
insert允许在容器中任意位置插入0个或者多个元素,vector,deque,list,string都支持,forward_list支持特殊版本的insert成员。
insert返回值为指向第一个新加入元素的迭代器。如果没有插入任何元素则返回第一个参数
vector<int> b = { 1,2,3 };
b.insert(b.end(),4); 1,2,3,4
b.insert(b.begin(), b.end() - 2, b.end()); 341234
b.insert(b.end(), 4, 5);3412345555
forward_list支持特殊版本的insert成员:
lst.insert_after(p,t)
lst.insert_after(p,n,t)
lst.insert_after(p,b,e)
lst.insert_after(p,il)
在迭代器p之后插入元素,t是一个对象,n是数量,b,e是表示范围的一对迭代器,il是一个花括号列表,返回一个指向最后一个插入元素的迭代器。
3.4 emplace
emplace_front,emplace,emplace_back。这些操作是构造而不是拷贝,对应push_front,insert,push_back.
当调用push,insert时我们将元素的对象传递给他们,然后被拷贝到容器中。调用emplace则将参数传递给元素类型的构造函数。假设c保存Sales_data类:
c.emplace_back("978-05",25,15);正确
c.push_back("978-05",25,15);错误
c.push_back(Sales_data("978-05",25,15))正确
c.emplace_back()使用Sales_data默认构造函数。
forward_list支持特殊版本的emplace成员:
emplace_after(p,args)使用args在p指定的位置创建一个元素,返回一个指向这个新元素的迭代器。
3.5 front,back,at
每个顺序容器都有一个front成员函数,返回容器中首元素的引用。
auto val = c.front() == auto val1=*c.begin()
除了forward_list之外的顺序容器都有一个back成员函数,返回尾元素的引用。
auto val2 = c.back() == auto val3=*(--c.end())
at只适用于string,vector,deque,array,返回下标n的元素的引用,如果下标越界,则抛出一out_of_range异常。
c.at(n)
提供快速随机访问的容器string,vector,deque,array也都提供了下标运算符,返回容器中该元素的引用。c.front=42;auto val=c.front() ;val=10不改变c。auto &val=c.front() ;val=10改变c。
给出的下标必须在范围内,下标运算符并不检查下标是否在合法范围内,使用越界的下标是一种严重的程序设计错误,而且编译器并不检查这种错误。可以使用at,如果越界则抛出异常。
vector<int> data;空vector
cout<<data[0];运行出错
cout<<data.at(0);抛出一个out_of_range异常。
3.6 pop_back,pop_front,erase,clear
array都不支持
c.pop_front(),删除c中首元素,vector,string和array不支持.若c为空,则函数行为未定义。函数返回void。
c.pop_back(),删除c中尾元素,forward_list不支持.若c为空,则函数行为未定义。函数返回void。
c.erase(p),删除迭代器p所指定的元素,返回一个指向被删除元素之后元素的迭代器,若p指向尾元素,则返回尾后迭代器。
c.erase(b,e)删除迭代器b和e所指定范围内的元素,返回一个指向最后一个被删除元素之后元素的迭代器。
forward_list支持特殊版本的erase成员:
lst.erase_after(p)
lst.erase_after(b,e)
删除p指定位置之后的元素,或删除从b之后直到但不包含e之间的元素的迭代器。返回一个指向被删除元素之后的迭代器。
c.clear()删除c中所有元素,返回void,==c.erase(c.begin(),c.end())
3.7 string额外操作
3.7.1 包含在cctype头文件中
c是字符,下列返回值都是为int类型
isalnum(c) 当c是字母或者数字为真
isalpha(c) 当c是字母为真
isdigit(c) 当c是数字为真
islower(c) 当c是小写字母为真
isupper(c) 当c是大写字母为真
isspace(c) 当c是空白字符为真
ispunct(c) 当c是标点为真
isprint(c) 当c是可打印字符为真
tolower(c) 返回小写字母
toupper(c) 返回大写字母
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string a1="zh1, an2";
int alpha = 0;
int digit = 0;
int punct = 0;
for (auto &i : a1)
{
if (isalpha(i))
++alpha;
if (isdigit(i))
++digit;
if (ispunct(i))
++punct;
i=toupper(i);
}
cout << alpha << endl;
cout << digit << endl;
cout << punct << endl;
cout << a1 << endl;
system("pause");
return 0;
}
4
2
1
ZH1, AN2
请按任意键继续. . .
3.7.2 substr
s.substr(pos,n)从pos开始n个字符拷贝,pos默认值为0,n默认值为s.size()-pos
string s("hello world");
string s2=s.substr(0,5); hello
string s3=s.sbustr(6); world
string s4=s.substr(6,11);world
3.7.3 数值转换
int i=42;
string s=to_string(i);
double d=stod(s);
int i=stoi(s)
string s2="pi=3.14"
d=stod(s2.substr(s2.find_first_of("+-1234567890")))
3.7.2 查找字符
s.find(args)查找s中args第一个出现的位置
string s("hello 123")
s.find('1')
s.rfind(args)最后一次出现位置
s.find_first_of(args) args中任意字符第一次出现位置
s.find_first_of("1234567890")
3.7.3 子串查找
#include<algorithm>
int main()
{
string a1="zh1, an2";
string a2 = "an";
string::iterator a_f=search(a1.begin(), a1.end(),a2.begin(),a2.end());
cout << a_f-a1.begin() << endl;
system("pause");
return 0;
}
4 容器操作可能使迭代器失效
4.1 vector、string
插入元素时,若引起空间重配,则迭代器、引用、指针都失效。
若未引起空间重配,则插入位置之前的迭代器、引用、指针仍有效,但指向插入位置之后的迭代器、引用、指针将会失效。
删除元素时,删除位置之前的迭代器、引用、指针仍有效,但删除位置之后的迭代器、引用、指针一律无效。
4.2 deque
插入元素时,若插入到除首尾位置之外的任何位置,都会引起迭代器、引用、指针失效。
如果在首尾位置插入元素,则迭代器失效,引用和指针不会失效。
删除元素时,若删除的不是首尾元素,则迭代器、引用、指针都会失效。若删除的是首元素,则除指向首元素的迭代器、引用、指针收到影响,指向其他元素的迭代器、引用、指针仍有效。删除尾元素也是一样,只有被删除的元素受到影响,其他不会受到影响。
4.3 list,forward_list
插入和删除元素时,其他迭代器、指针、引用都仍然有效!
5.容器适配器
适配器是标准库中的一个通用概念。容器,迭代器和函数都有适配器,本质上一个适配器是一种机制,能使某种事物的行为看起来像另外一种事物。
5.1 stack
堆栈适配器,先进后出。
stack<int>intstack;
s.pop()删除栈顶元素
s.push(item)创建一个新元素压入栈顶
s.emplace(args)
s.top()返回栈顶元素,但不将元素弹出栈
5.2 queue,priority_queue
队列适配器,先进先出
定义一个queue的变量 queue<Type> M
查看是否为空范例 M.empty() 是的话返回1,不是返回0;
从已有元素后面增加元素 M.push()
输出现有元素的个数 M.size()
显示第一个元素 M.front()
显示最后一个元素 M.back()
清除第一个元素 M.pop()
priority_queue提供了三个基本函数,分别是:
top()
push()
pop()
注意,pop并不会返回元素,top才会返回堆顶的元素。
stack:底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时。只要求push_back,pop_back,back操作,可以使用除了array和forword_list之外的其他容器来构造容器。
queue:底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时(stack和queue其实是适配器,而不叫容器,因为是对容器的再封装)。要求back,front,push_back,push_front,因此可以构造在list和deque上。
priority_queue:的底层数据结构一般为vector为底层容器,堆heap为处理规则来管理底层容器实现,除了front,push_back,pop_back,之外还要随机访问能力,可以构造在vector或deque上。
创建一个适配器将一个命名的顺序容器作为第二个参数类型。
vector<int> data{1,2,3,4};
stack<int, vector<int> >da(data);
所有适配器都要求容器具有添加和删除元素的能力,因此不能构建在array上
所有适配器都要求容器具有添加,删除以及访问尾元素的能力,因此不能构造在forward_list上
C++笔记之——顺序容器
猜你喜欢
转载自blog.csdn.net/zd_nupt/article/details/80526209
今日推荐
周排行