前言:最近在刷oj,用到了不少C++的STL里面的类。虽然学校的课堂上没有讲过这些,但由于自己之前在啃《C++ Primer》的时候多多少少也了解到一些,所以一些常用的类还是知道的,但还是不得不感慨,人的记忆力啊...多多少少也遗忘了一些。现在又重新学习了STL里常用类及函数,为了避免以后忘记了,就来好好做个总结吧!
目录
vector类
vector这个类在我刷oj的时候几乎是用得最多的了。
认识
在www.cplusplus.com中,对于该类的定义与说明是这样的:
vector是一个可以改变大小的数组的序列容器。
就像数组一样,vector为它们的元素使用连续的存储位置,这意味着它们的元素也可以通过对其元素的常规指针的偏移量来访问,并且和数组一样高效。但与数组不同的是,它们的大小可以动态变化,它们的存储由容器自动处理。
在内部,vector使用动态分配的阵列来存储它们的元素。这个数组可能需要重新分配,以便在插入新元素时增加大小,这意味着分配一个新的数组并将所有元素移动到它。在处理时间方面,这是一项相对昂贵的任务,因此,在每次将元件添加到集装箱时,vector不会重新分配。
相反,vector容器可能会分配一些额外的存储空间来适应可能的增长,因此容器的实际容量可能比包含其元素所需的存储空间更大(例如它的大小)。库可以实现增长不同的策略来平衡内存使用和重新分配,但在任何情况下,重新分配应该只发生在对数生长间隔的大小,以便插入单个元素的vector可以提供平摊常数时间复杂度(见push_back方法)。
因此,与数组相比,vector消耗更多的内存,以换取管理存储和动态增长的能力。
与其他动态序列容器(deque、list和forward_list)相比,vector非常高效地访问其元素(就像数组一样),并且相对高效地添加或删除其末端的元素。对于涉及到在除端以外的位置插入或删除元素的操作,它们的性能比其他的要差,并且比list和forward_list的迭代器和引用的一致性要少。
使用
vector 是向量类型,它可以容纳许多类型的数据,如若干个整数,所以称其为容器。vector 是C++ STL的一个重要成员,使用它时需要包含头文件,实例代码如下:
#include <vector>
构造方法
由于该类是一个模板类,所以我们在构造对象时,应当声明存储的变量的类型或者类。如;vector<int> 或者vector<string>...
也就是说这个容器是可以存储我们自定义的类的。这其实跟Java里面的容器的概念其实是一样的。
该类的构造方法有五个:
// constructing vectors
#include <iostream>
#include <vector>
int main ()
{
// constructors used in the same order as described above:
std::vector<int> first; // empty vector of ints
std::vector<int> second (4,100); // four ints with value 100
std::vector<int> third (second.begin(),second.end()); // iterating through second
std::vector<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
std::cout << "The contents of fifth are:";
for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
输出结果如下:
常用函数总结
(1)a.assign(b.begin(), b.begin()+3); //b为向量,将b的0~2个元素构成的向量赋给a
(2)a.assign(4,2); //是a只含4个元素,且每个元素为2
(3)a.back(); //返回a的最后一个元素
(4)a.front(); //返回a的第一个元素
(5)a[i]; //返回a的第i个元素,当且仅当a[i]存在
(6)a.clear(); //清空a中的元素
(7)a.empty(); //判断a是否为空,空则返回ture,不空则返回false
(8)a.pop_back(); //删除a向量的最后一个元素
(9)a.erase(a.begin()+1,a.begin()+3); //删除a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)
(10)a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5
(11)a.insert(a.begin()+1,5); //在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
(12)a.insert(a.begin()+1,3,5); //在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5 (13)a.insert(a.begin()+1,b+3,b+6); //b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8,插入元素后为1,4,5,9,2,3,4,5,9,8
(14)a.size(); //返回a中元素的个数;
(15)a.capacity(); //返回a在内存中总共可以容纳的元素个数
(16)a.resize(10); //将a的现有元素个数调至10个,多则删,少则补,其值随机
(17)a.resize(10,2); //将a的现有元素个数调至10个,多则删,少则补,其值为2
(18)a.reserve(100); //将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能)
(19)a.swap(b); //b为向量,将a中的元素和b中的元素进行整体性交换
(20)a==b; //b为向量,向量的比较操作还有!=,>=,<=,>,<
从vector中读取元素
第一种方法当然是司空见惯的按照下标读取了,实例代码如下:
int a[7]={1,2,3,4,5,6,7};
vector<int> b(a,a+5);
for(int i=0;i<=b.size()-1;i++)
cout<<b[i]<<" ";
第二种方法则是有些新鲜使用迭代器进行读取,示例代码如下:
int a[7]={1,2,3,4,5,6,7};
vector<int> b(a,a+5);
for(vector<int>::iterator it=b.begin();it!=b.end();it++)
cout<<*it<<" ";
list类
认识
list是一个序列容器,它允许在序列中的任何地方进行持续时间插入和删除操作,并在两个方向上进行迭代。
list容器被实现为双链表;双链表可以存储处在不同位置并且不连续的元素。而链表内部的顺序是由容器内部维持着每一个元素都有着一个指向前一个元素以及指向后一个元素的指针。
它们与forward_list非常相似:主要的区别在于,forward_list对象是单链表,因此它们只能迭代向前,以换取更小、更高效。
与其他基本的标准序列容器(array、vector和deque)相比,list在插入、提取和移动元素的任何位置上的元素都表现得更好,在这个容器中已经获得了迭代器,因此也在算法中进行了大量的使用,比如排序算法。
与其他序列容器相比,list和forward_list的主要缺点是,它们无法直接访问这些元素的位置;例如,要访问列表中的第六个元素,必须从已知位置(如开始或结束)到该位置进行迭代,这在它们之间的距离中需要线性时间。它们还会消耗一些额外的内存,以保持与每个元素相关联的链接信息(这可能是大型小型元素列表的一个重要因素)
使用
构造方法
list的构造方法总共有五种,实例代码如下:
// constructing lists
#include <iostream>
#include <list>
int main ()
{
// constructors used in the same order as described above:
std::list<int> first; // empty list of ints
std::list<int> second (4,100); // four ints with value 100
std::list<int> third (second.begin(),second.end()); // iterating through second
std::list<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
std::cout << "The contents of fifth are: ";
for (std::list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
std::cout << *it << ' ';
std::cout << '\n';
return 0;
}
输出结果如下:
常用函数
a.assign() //给list赋值
a.back() //返回最后一个元素
a.begin() //返回指向第一个元素的迭代器
a.clear() //删除所有元素
a.empty()/ /如果list是空的则返回true
a.end() //返回末尾的迭代器
a.erase()// 删除一个元素
a.front() //返回第一个元素
a.get_allocator() //返回list的配置器
a.insert() //插入一个元素到list中
a.max_size() //返回list能容纳的最大元素数量
a.merge() //合并两个list
a.pop_back() //删除最后一个元素
a.pop_front() //删除第一个元素
a.push_back() //在list的末尾添加一个元素
a.push_front() //在list的头部添加一个元素
a.rbegin() //返回指向第一个元素的逆向迭代器
a.remove() //从list删除元素
a.remove_if() //按指定条件删除元素
a.rend() //指向list末尾的逆向迭代器
a.resize() //改变list的大小
a.reverse() //把list的元素倒转
a.size() //返回list中的元素个数
a.sort() //给list排序
a.splice() //合并两个list
a.swap() //交换两个list
a.unique() //删除list中重复的元素
读取方法
使用迭代器进行读取操作
for(list<int>::const_iterator it = lst1.begin();it != lst1.end();it++)
{
cout<<*it;
}
cout<<endl;