总结STL中vector,set,multiset,map,multimap,deque,stack,list,queue,priority_queue,string的优缺点以及基本的函数用法。

STL存在的意义就是把c语言中数据结构的很多很多的代码封装成一个个函数名,方便调用,提高效率。

vector(数组)

#include<vector>
vector<int> a;//vector基本上就是数组二代,拥有数组的所以功能,还优化了用法。
a.push_back();//尾插
a.insert(a.begin(),b)//最前面插入b
a.erase(a.begin()+1,a.begin()+3)//删除a[1],a[2],这个用法真的老是记错呀,区间左闭右开,记住记住记住!
a.clear();
reverse(a.begin(),a.end());//逆序
sort(a.begin(),a.end())//排序
a.size()//长度
a.empty()//判断是否为空
find()//时间复杂度为O(n)(即将整个向量容器遍历了一遍)
//用法借助迭代器
vector<int>::iterator it;
it=find(a.begin(),a.end(),b)
it!=a.end()//找到了b

优点:不用定义长度,可逆序,可快排,清空容器简单clear。

缺点:find不好用,时间复杂度高。erase不好用,删除元素麻烦。

特别的用法:查找一个字符串是否是另一个字符串的子串。如果是,返回值为0,如果不是,返回值为数字乱码。

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
vector<string> a;
a.push_back("111");
a.push_back("112");
a.push_back("511");
a.push_back("11");
cout<<a[0].find(a[3])<<endl;
}

deque(双端队列)

头部尾部都可以插入和删除元素,尾插会扩张队列,而头插和insert插入只会覆盖原有的元素(这个设定很奇怪,不明白有什么用。。。),deque在练习STL习题的时候没用过,如何需要用队列这个数据结构的话,我都是用queue,就不说deque的优缺点了,总之函数用法和vector很像。

stack(堆栈)

#include<stack>
stack<int> a;
a.push(b);//入栈
a.top();//访问栈顶元素
a.pop();//栈顶元素出栈
a.size();
a.empty();

都是基本操作,没啥说的。。。

list(双向链表)

ps:先吐槽一下,目前我还不知道怎么用STL创建一个循环链表,百度了一波也没个结果,如果有大神会的,私信me呀。。。

#include<list>
list<int> a;
a.push_back(b);//尾插
a.push_front(b);//头插
list<int>::iterator it;
it=a.begin();
a.insert(it,b);//往第一个元素的后面插入b,链表自动扩张
a.pop_front();//删除首元素
a.pop_back();//删除尾元素
remove(b);//删除等于b的所有元素
a.erase();
find();
a.clear();
a.sort();
a.unique();//剔除连续重复的元素只剩一个
//例如2 8 1 1 1 5 1变成2 8 1 5 1

优点 :可以用快排sort,删除函数remove好用,有一个特别的函数unique。

缺点:find搜索时间复杂度高,删除函数erase不好用。

queue(队列)

#include<queue>
queue<int> a;
a.push(b);//入队
a.pop();//出队
a.front();//读取队头
a.back();//读取队尾
a.empty();
a.size();

没什么好说的,就是一个数据结构,先进先出,即元素只能从队尾插入,队头删除。

priority_queue(优先队列)

优点:相较于queue,入队的元素会由大到小自动排列。这个结构很好用,构很好用,很好用,好用,用!

缺点:queue读取队头的函数是a.front(),而priority_queue读取队头的函数是a.top(),为什么要改呢?很容易记错的。。。而且和queue一样没有clear()清空函数,差评!

清空队列:

while(a.empty()!=ture)
{
a.pop();
}

特别的:

和其他的不一样,这个<是按从小到大排列

struct Info
{
string a;
int b;
bool operator < (const Info &p)const
{
//按a由小到大排列
return p.a<a;
}
};

set

#include<set>//黑白树 
set<int> a;
a.inset(b);//插入b,插入元素会自动有小到大顺序排序
a.erase(b);//删除b
a.find(b)!=a.end();//找到了b
a.clear();

结构体,需要内部重载排序:(set,multiset,map,multimap用法一样)

struct Info
{
string a;
int b;
bool operator < (const Info &p)const
{
//按a由大到小排列
return p.a<a;
}
};

 

优点:采用中序遍历,检索快,find()时间复杂度低,自动升序排序,删除元素简单。

缺点:不能插入相同元素。有时候这个特性也是优点。

multiset

优点:相较于set,允许插入相同的元素,使用删除函数erase时,返回值为删除元素的个数。

缺点:使用find函数时,如果查找的元素有多个,只会返回第一个重复元素的迭代器位置。

map

函数用法和set一样,同样采用黑白树结构,唯一不用的只是键值后果跟了一个映照数据,这也是map的亮点呀!

优点:和set一样,find函数搜索极快,插入按照键值升序排列,删除元素简单,它的结构就是最大的优点。map的查找是对数时间的。对于2的32次方个元素,只需查找32次。由此可见map的高效。

缺点嘛目前用着没毛病。。。

multimap

允许插入重复的键值。

string(字符串)

string s1(s,i,len);这个定义很好用,s是一个字符串,s中下标i到i+len的字符赋值给s1。

s1.find(s2);在s1中查找s2,如果找到就返回所在的第一个下标,找不到就返回很大的一个数,时间复杂度是很高的,比KMP慢很多。

string s1(a.rbegin(),a.rend());这个操作可以把a逆序赋值给s1。

总结:

如果你需要一个搜索快的结构,当然是选择黑白树啦,即可以用map,multimap,set,multiset,而其他的采用线性结构,搜索时间复杂度就很高。如果你需要一个插入就排好序的结构,优先队列priority_queue是首选,其次是map,multimap,set,multiset,如果你需要删除方便的结构,当然还是选map,multimap,set,multiset。结构内含快排的有list和vector。目前很常用的就是map,priority_queue,set,queue,vector。结构内不含清空函数clear的:stack,queue,priority_queue。其实clear的底层实现是erase(map.begin(),map.end()).所以没有erase函数就没有clear函数喽。

不断更新中。。。未完待续