【STL】单向链表forward_list 和 数组array

14天阅读挑战赛

前言

由于本文涉及内容比较多,为了尽可能的讲详细些,会把各种例子附上,所以代码样例会比较多,也为了更好的布局,本系列将分开讲解,并且前期为了更加贴合实战需求,暂时只对一些常用的STL容器和基本功能进行讲解。

为了使每篇文章具有一定的独立性,后续的文章大多数会将之前文章涉及的知识点中提取,并且在后续会将相应的例子补上。

本文STL系列知识参考《C++语言程序涉及(第5版)》

STL指南

单向链表

与手写的单向链表具有相当的性能,forward_list 不支持size操作

注意事项

forward_list 与list不同,它是一个单向链表,每个结点只有指向后一个结点地指针,由于没有简单办法获取结点的前驱,所以forward_list的添加和删除操作是通过改变给定元素之后的元素完成的。

并且需要注意,forward_list并没有insert,emplace和erase操作
但是它有insert_after/emplace_after/erase_after操作,其参数与list的insert/emplace和erase相同,但并不是插入或删除p1所指的元素,而是p1之后的元素

例如想要删除forward_list中位于第3个位置处的元素,使用erase_after,并且p1应该指向第二个元素

构造函数

除了使用默认构造函数外,还可以使用给定的元素构造,或者使用已有迭代器的区间所表示的序列来构造

1. S s(n,t);

构造一个由n个t元素构成的容器实例s

int main() {
    
    
    vector<int>vec1(4,1);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
}
1 1 1 1

2. S s(n);

构造含有n个大小空间的实例s,每个元素都为默认构造函数T()构造的对象

int main() {
    
    
    vector<int>vec1(4);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
}
0 0 0 0

3. s(q1,q2);

将[q1,q2)区间内的数据作为s的元素构造s

int main() {
    
    
    int a[]={
    
    1,2,3,4};
    vector<int>vec1(a,a+4);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
}
1 2 3 4
int main() {
    
    
    list<int>l(4,2);
    vector<int>vec1(l.begin(),l.end());
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
}
2 2 2 2

请注意:下面这串代码就是上一篇博客所说的,这种初始化方法是不对的,它会报错

 vector<int>vec1(l.begin(),l.begin()+2);

赋值函数

使用赋值函数时,将会把原有元素全都覆盖

1. s.assign(n,t)

赋值后的s由n个t元素组成,相当于把s用n个t初始化

int main() {
    
    
    list<int>l(4,2);
    vector<int>vec1(l.begin(),l.end());
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    vec1.assign(3,1);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
}
2 2 2 2 
1 1 1
int main() {
    
    
    list<int>l(4,2);
    vector<int>vec1(l.begin(),l.end());
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    vec1.assign(5,1);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
}
2 2 2 2 
1 1 1 1 1

s.assign(n)
赋值后的s由n个默认构造函数T()构造的元素组成
这个赋值方法在验证时报错了,所以这里不推荐使用这个

2. s.assign(q1,q2)

赋值后的s的元素为[q1,q2)区间内的元素

int main() {
    
    
    list<int>l(4,2);
    int a[]={
    
    1,2,3,4,5};
    deque<int>vec1(l.begin(),l.end());
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    vec1.assign(a,a+5);
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
}
2 2 2 2 
1 2 3 4 5
int main() {
    
    
    list<int>l(4,2);
    vector<int>vec={
    
    1,2,3,4,5};
    deque<int>vec1(l.begin(),l.end());
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    vec1.assign(vec.begin(),vec.begin()+5);//此处assign可以使用vec.begin()+n,而在初始化时不可以
    copy(vec1.begin(),vec1.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
}
2 2 2 2       
1 2 3 4 5 

元素插入

可以一次插入一个或多个指定元素,也可以将一个迭代器区间所表示的序列插入,插入时需要一个指向s的迭代器表示插入位置。

1. s.insert_after(p1,t)

在p1位置后插入元素t,返回一个指向新元素的迭代器

2. s.insert_after(p1,n,t)

在p1位置后插入n个元素t

3. s.insert_after(p1,q1,q2)

在p1位置后插入[q1,q2)区间的元素

4. s.emplace_after(p1,args)

将参数args传递给T的构造函数构造新元素t,插在p1位置后,返回指向新元素的迭代器

元素删除

1. s1.erase_after(p1)

删除s1中p1指向的元素,返回被删除的下一个元素的迭代器

2. s1.erase_after(p1,p2)

删除s1中[p1,p2)区间的元素,返回p2指向的元素的迭代器

改变容器大小

1. s.resize(n)

将容器s大小改为n,若原容器s大小大于n,则末尾多余元素被删除,否则在容器末尾用T()填充

首尾元素的直接访问

1. s.front()

获得首元素的引用

2. s.back()

获得尾元素的引用(不包括forward_list)

在容器尾部插入、删除元素

1. s.push_back(t)

向尾部插入元素t

2. s.emplace_after(args)

将args传递给T的构造函数构造新元素t,向尾部插入新元素

3. s.pop_back()

将容器尾部的元素删除

在容器头部插入、删除元素

1. s.push_front(t)

向头部插入于是元素t

2. s.pop_front()

删除容器头部的元素t

容器列表初始化

c++11支持顺序容器列表初始化,可以直接用列表的元素实例来创建一个新的顺序容器对象,并且隐式地将列表元素个数指定为新建容器大小(定长数组array需指定大小)

如:

list<int>numberSeq={
    
    1,4,7,9};//包含4个元素的列表容器对象
vector<string>strs={
    
    "hello","world"};//包含2个string元素的向量容器对象

数组

array对内置数组进行了封装,提供了更安全、更方便地使用数组地方式

大小固定

定义时需要提供指定元素类型和指定容器大小

构造函数

之前介绍的容器操作几乎都不适用于array,array不能动态改变容器大小,在定义时应该需要显示的指明容器大小

如:

array<int,10>arr;//arr为保存了10个int类型的数组
array<string,20>astr;//astr为保存了20个string类型的数组
array<int,10>arrl={
    
    1,2,3,4};//可以通过列表进行初始化

与其他容器不同,默认构造的array时非空的。使用列表初始化时,初始值的数目必须小于等于array大小。

赋值操作

虽然不能对内置数组类型进行赋值或者对象赋值操作,但array并无此限制

int main() {
    
    
    array<int,10>arr;//arr为保存了10个int类型的数组
    array<string,20>astr;//astr为保存了20个string类型的数组
    array<int,10>arrl={
    
    1,2,3,4};//可以通过列表进行初始化
    copy(arrl.begin(),arrl.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    copy(arr.begin(),arr.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
    arr=arrl;
    copy(arr.begin(),arr.end(),ostream_iterator<int>(cout," "));
    cout<<endl;
}
1 2 3 4 0 0 0 0 0 0 
0 0 4200391 0 4199744 0 8 0 0 0 
1 2 3 4 0 0 0 0 0 0 

猜你喜欢

转载自blog.csdn.net/weixin_45720193/article/details/127573351