【注】本文适合STL新手,包括今年就要秋招的广大朋友,可以让你们快速上手STL
最近刷题,发现好多题都需要用到STL才可以做,想到之前学了一遍但是没有很好地掌握,我就决定重新复习一遍,现在把我觉得重要的接口使用总结下来写成一篇博客,希望可以对你们有所帮助
vector常用接口
//构造一个空的vector
vector<int>v1;
//构造一个空的vector ,但是底层空间大小设置为20个元素
vector<int>v2(20);
int array[] ={1,2,3,4,5,6,7,8,9,0};
//构造一个vector对象,并用数组进行初始化
vector<int>v3(array,array+sizeof(array)/sizeof(array[0]));
v.push_back() //尾插
v.pop_back() //尾删
v.insert(v.begin(),0) //任意位置插入
v.insert(v.end(),3,4);//在末尾插入3个4
//迭代器
vector<int>v::iterator it = v.begin();
while(it != v.end())
cout<<*it++<<" ";
cout<<endl;
v.erase(v.begin()) //删除任意位置
v.erase(v.begin(),v.begin()+3) //删除指定区间的元素
//assign()方法是给vector进行赋值,在进行赋值之前,该方法会先将vector中原有的旧元素erase掉,然后再将新元素插入进去
v.assign(5,10)//给vector五个值为10的元素
v.clear() //将vector中元素清空,底层容量不变
v.assign(array,array+sizeof(array)/sizeof(array[0])); //将数组赋给vector
v.resize(n,data)//将vector中的元素改变到n个,第二个参数可以不用传,使用缺省值,将vector中的元素缩小到5个,缩小时底层容量不变,当增加到超过vector的个数时,就会增容
list常用接口
- 由于vector底层搭载一段连续空间,在其任意位置进行数据的插入和删除时效率是非常低下的(O(N)),因此当集合中需要进行大量的插入和删除操作时,可以考虑list,因为list底层结构为链表,在任意位置进行数据插入操作的时间复杂度均为O(1)
- list的底层结构
- list的底层结构是一个带头结点的双向循环链表,因此在其任意位置进行数据插入和删除操作都是非常方便的,这里一定要记住是双向链表,可以保证从那一头都可以实现插入和删除,因此效率很高
- list的迭代器
- list的迭代器需要自己来实现,因为list是一个双向链表,不知道该朝前走还是朝后走,所以由使用者自己实现,只需要重载一下即可
void TestList()
{
//用数组来初始化list
list<int>l3(array,array+sizeof(array)/sizeof(array[0]));
l.push_back(1); //尾插
l.pop_back(); //尾删
l.push_front(1); //头插
l.pop_front(); //头删
//迭代器
list<int>::iterator it4 = l4.begin();
while(it4 != l4.end())
cout<<*it4++;
cout<<endl;
list<int>::reverse_iterator it5 = l4.rbegin();//逆向遍历
l.assign(array,array+sizeof(array)/sizeof(array[0])); //赋值
cout<<l.front()<<endl; //获取链表的第一个元素
cout<<l.back()<<endl; //获取链表的最后一个元素
l.remove(3); //直接删除一个元素
l.unique(); //将连在一起的相同数据删除,只保留一个
l.sort(); //排序
merge:将两个有序的链表合并成一个链表,合并后依然有序
//reverse:链表的逆置
}
deque 双端队列
- vector是单向开口的线性连续空间,deque是双向开口的线性连续空间,所谓双向开口,是指可以在头尾两段分别进行元素的插入和删除操作,因此deque允许常数时间内对头端进行数据的插入操作
- 2.deque的底层结构:deque是一段假想的连续空间,与vector不同。deque是由一段一段定量的连续空间构成,一旦有必要在deque的前端或者尾端增加新空间,便配置一段定量连续空间,串接在整个deque的头端和尾端,而deque的任意就是:在分段的定量连续空间上维护其连续的假象
- 3.deque的迭代器:因为deque是分段连续的,维护其“整体连续”假象的任务就落在其迭代器operator ++和operator–上。因此deque的迭代器必须要知道分段连续空间在哪里,齐次它必须能够识别出自己是否处于某段连续空间的边缘,如果是,一旦前进或后退时就必须跳到下一个或上一个分段空间
deque的用法
std::deque<int> second (4,100);
std::deque<int> fourth (third);
std::deque<int> third (second.begin(),second.end());
deque.assign() //赋值,可以通过迭代器赋值,可以直接用数组赋值
deque operator= //右边赋值给左边之后为空
deque.at(i)=i //通过下标赋值,也能通过下标使用值
deque.erase() //删除任意位置或者区间的值
auto it = mydeque.emplace ( mydeque.begin()+1, 100 ); //在一个位置的后面加一个值
mydeque.emplace ( it, 200 );
mydeque.emplace ( mydeque.end(), 300 );
std::cout << "mydeque contains:";
for (auto& x: mydeque)
std::cout << ' ' << x;
for (int i=1; i<6; i++) mydeque.push_back(i); // 1 2 3 4 5
std::deque<int>::iterator it = mydeque.begin();
++it;
it = mydeque.insert (it,10); // 1 10 2 3 4 5
// "it" now points to the newly inserted 10
mydeque.insert (it,2,20); // 1 20 20 10 2 3 4 5
// "it" no longer valid!
deque operator []来表示下标元素
deque.resize() //重新设置大小,如果只传一个参数就补0
deque1.swap(deque2) //交换两个deque中的元素
stack的使用接口
栈是由双端队列的适配器·适配出来的,因为栈是后进先出的性质,而双端队列两头都可以进行操作,因此十分方便,其实list也可以作为栈的适配器,不过双端队列对于数据的操作应该说是更加方便的。
- stack的底层使用双端队列通过适配器来实现的
- stack<int>mystack;
mystack.push(1); //尾插
mystack.pop(); //头删
stack<int>stack1,stack2;
stack1.swap(stack2) //交换两个栈的元素
#### queue的底层也是由deque实现
template
#### map的使用
- map的特性是:所有元素都会根据元素的键值key自动排序,其中的每个元素都是<key,value>的键值对,map中不允许有键值相同的元素,因此map中元素的键值key不能被修改,但是可以通过key修改对应的value。如果一定要修改与value对应的key,可将已存在的可用删除掉,然后重新插入
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > // map::allocator_type
> class map;
//map.at意思是给key对应的value赋值
std::map<std::string,int> mymap = {
{ "alpha", 0 },
{ "beta", 0 },
{ "gamma", 0 } };
mymap.at("alpha") = 10;
mymap.at("beta") = 20;
mymap.at("gamma") = 30;
for (auto& x: mymap) {
std::cout << x.first << ": " << x.second << '\n';
}
还有一些常见的STL算法我会在下一篇博客里面详细说明的,对于STL的学习和使用,我们不能只建立在懂得原理上,我们还应该直到他们底层是怎么实现的,这样才有助于理解。
注:
本文如有纰漏之处,欢迎大家进行指正,我定虚心改进。