目录
STL(Standard Template Library)学习汇总
STL(Standard Template Library)学习汇总
1.为什么选择STL?
STL的可读性极佳,运用极广,被选为GNU C++的标准程序库,又开放自由运用。不仅最为人广泛运用的各种数据结构和算法在STL中有良好的实现,连内存配置与管理也都重重考虑了最佳效能。一切的一切,除了实现软件积木的高度复用性,让各种组件得以灵活搭配运用,更考虑了实现上的关键议题:效率
2.STL—vector
vector的概念:
vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值。vector的数据安排及操作方式与array非常相似,唯一的差别在于array是静态空间,一旦配置了就不能改变;vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。vector不是一种数据类型,而只是一个类模版,可以用来定义多种数据类型。在定义了vector对象之后,vector类型的每一种都指定了其保存元素的类型。
vector的头文件:#include <vector>
vector的声明:
vector < int > v; // 定义一个空的vector,vector可以存放任意类型的数据
vector < int > v[100]; //相当于二维数组,大多数用于临界表的建立,v[i]代表从i出发的边,vector里存的是边
vector < int > v(4,5); // 定义了一个大小为4的vector 初始化为5
vector < int > v{1,2,-3,4,7,8}; // 定义一个vector 里面含有 1,2,-3,4,7,8
vector的方法:
push_back() //在数组尾部添加一个元素
pop_back() //去掉数组最后一个元素
erase() // 删除一个元素
resize(5) //重置大小,不赋值默认为0
front() //获得数组第一个元素
*v.begin() // 获得第一个元素
back() // 获得最后一个元素
size() // 获得元素个数
vector的遍历:
首先我们应该知道什么是迭代器: 它你可以理解为指针。
//迭代器: for(vector < int > :: iterator it = v.begin(); it != v.end(); it++) cout<<*it; //迭代器循环 //迭代器简化: for(auto it = v.begin(); it != v.end(); it++) cout<<*it; //迭代器简化循环 //c++11新特性: for(auto x:v) cout<<x; // c++11新特性
vector的排序与反转:
首先我们要知道algorithm:algorithm是对容器继承的一些算法函数,辅助刷算法题。
排序:
//使用sort函数: sort(v.begin(),v.end(),less<int>()); //从小到大 sort(v.begin(),v.end(),greater<int>()); //从大到小排序
反转:
//使用reverse函数: reverse(v.begin(), v.end());//元素翻转
vector的获取元素:
vector < int > v{1,2,-3,4,7,8};
cout<<v[4] // 获得元素 7
cout<<v.at(3) // 获得元素 4
3.STL—stack(栈 后进先出)
stack的概念:
stack即栈,允许新增元素、移除元素、取得最顶端元素。但除了最顶端外,没有任何其他方法可以存取stack的其他元素,stack不允许随机访问。stack所有元素的进出都必须符合“后进先出”的条件,只有stack顶端的元素,才有机会被外界取用。stack不提供走访功能,也不提供迭代器。
stack的头文件:#include <stack>
stack的声明:
stack < type > s; //可以存放任意类型的数据
stack的方法:
push() // 压入一个元素
pop() // 弹出一个元素
top() // 获取栈顶元素
size() //获取元素个数
empty() // 有元素为false 无元素为true
运用stack的经典例子:
进制转换(十进制转二进制)
int change(int number) { stack <int> s; int ans = 0; while(number > 0) { s.push(number % 2); number /= 2; } while(!s.empty()) { ans = ans * 10 + s.top(); s.pop(); } return ans; }
单词逆序(拓展sstream)
输入 :I love ACM
输出:ACM love l
#include <iostream> #include <stack> #include <sstream> using namespace std; int main(){ string str; stack <string> s; getline(cin,str); stringstream ss; ss<<str; while(ss>>str) { s.push(str); } while(!s.empty()) { cout<<s.top(); s.pop(); if(s.size() != 0) cout<<" "; } return 0; }
4.STL—queue(队列 先进先出)
queue的概念:
queue即普通队列,允许新增元素、移除元素、从最底端加入元素、取得最顶端元素。但除了最底端可以加入、最顶端可以取出,没有任何其他方法可以存取queue的其他元素。queue不支持随机访问。
queue的头文件:#include <queue>
queue的声明:
queue < type > Q; //可以存放任意类型
queue的方法:
Q.empty();// 查看是否为空,如果为空返回true
Q.push();// 在队尾增加元素
Q.pop();// 弹出队首第一个元素
Q.size();//显示队列中现有元素数量
Q.front();//显示队首第一个元素
Q.back();//显示队尾最后一个元素
5.STL—priority_queue(优先队列)
priority_queue的概念:
优先队列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)priority_queue允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放置在比它优先级低的元素前面,即提供了一种插队策略。标准库默认使用<操作符来确定他们之间的优先级关系,即权重大的排在队首。
priority_queue的头文件:#include <queue>
priority_queue的声明:
priority_queue<type, container, comp> Q;
type为队列操作的数据类型;container为实现队列所用的容器类型,必须是用数组实现的容器,比如 vector, deque 但不能用 list;comp为排队策略。
priority_queue<int, vector<int>, less<int> > Q;
priority_queue 模板类有三个模板参数,第一个是元素类型,第二个是保存数据的容器,第三个是比较方式。其中后两个都可以省略,默认容器为vector,默认的比较方式是数值上的小于关系,即用operator<,此时队列中元素由队头到队尾从大到小排列,如果把后面两个参数缺省的话,优先队列就是大根堆,队头元素最大。(注意这里的大根堆并不是数据结构意义上的大根堆。priority_queue只是保证第一个结点最大)
构造举例子:
/* 前两个参数没什么说的,很好理解,其中第三个参数,默认有三种写法,小顶堆:greater、大顶堆:less; 如果想自定义优先级而type不是基本类型,而是复杂类型,例如结构体、类对象,则必须重载其中的operator()。 */ /*基本类型*/ #include <iostream> #include <algorithm> #include <queue> using namespace std; int main() { priority_queue <int> Q1; //默认大根堆 priority_queue <int,vector<int>,greater<int>> Q2; //小根堆 priority_queue <int,vector<int>,less<int>> Q3; //大根堆 } /*复杂类型*/ #include <iostream> #include <algorithm> #include <queue> using namespace std; struct Node{ //以距离长短为依据的自定义小根堆 int dis,pos;// dis为最短距离,pos为是编号 。 bool operator <(const Node &x) const { return x.dis < dis; // 小根堆 //return x.dis > dis //大根堆 } }; int main() { priority_queue <Node> Q4; //自定义小根堆 }
priority_queue的方法:
priority_queue <int> Q;
Q.empty();//判断是否为空
Q.size();//优先队列中元素个数
Q.pop();//删除队首元素
Q.top();//查看优先级最高的元素
Q.push();//进入队列中对应优先级的位置
6.STL—map(映射)
map的概念:
map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value。map中所有元素都会根据元素的Key自动被排序。同时map不允许两个元素有相同的键值。
map的头文件
#include<map>
。
map的声明:
map <int,string> M;
map的使用:
插入元素:
map <int,string> M; //使用insert函数插入pair M.insert(pair<int,string>(111,"mapmap")); //使用insert函数插入value_type数据 M.insert(map<int,string>::value_type(222,"lili")); //使用array的方法插入 M[333] = "sisi";
寻找元素:
/* 如果M中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回结束游标end()。*/ map <int,string>::iterator it = M.find(k); /*返回m中键值等于k的元素的个数。*/ int cnt = M.count(k); /* 对于map对象,由于map中不存在相同的两个或者多个键,所以count成员的返回值只能是0或者1,用于检查map对象中某键是否存在。 find成员返回的是指向元素的迭代器,如果元素不存在,则返回end迭代器。 */
删除元素:
int ans = M.erase(k); // 删除m中键为k的元素,返回size_type类型的值,表示删除元素的个数。 map <int,string>::iterator it = M.erase(p); //从m中删除迭代器p所指向的元素,p必须指向m中确实存在的元素, //而且不能等于m.end(),返回void类型。
清空元素:
//用迭代器范围刪除 : 把整个map清空 M.erase(M.begin(), M.end()); //使用函数清空 M.clear();
map基本函数:
M.begin();//返回指向map头部的迭代器 M.end();//返回指向map末尾的迭代器 M.size();//返回map中元素的个数 M.rbegin();//返回一个指向map尾部的逆向迭代器 M.rend();//返回一个指向map头部的逆向迭代器 M.max_size();//返回可以容纳的最大元素个数
map的遍历:
有三种遍历方法具体如下:
#include <iostream> #include <algorithm> #include <map> using namespace std; int main() { //构造map map <int,string> M; //使用insert函数插入pair M.insert(pair<int,string>(1,"mapmap")); //使用insert函数插入value_type数据 M.insert(map<int,string>::value_type(4,"lili")); //使用array的方法插入 M[3] = "sisi"; M[2] = "kkkccc"; map <int,string>::iterator it;//迭代器 //方法一:利用迭代器 for(it = M.begin(); it != M.end(); it++) cout<<it->first<<" "<<it->second<<endl; //方法二:利用反向迭代器 for(it = M.rbegin(); it != M.rend(); it++) cout<<it->first<<" "<<it->second<<endl; //方法三:数组遍历 for(int i = 1; i <= M.size(); i++) cout<<M[i]<<endl; return 0; }
7.STL—set
set概念:
map容器是键值对的集合,而set容器只是单纯的键的集合,当只想知道一个值是否存在时,使用set容器是最合适的。在set中,所有元素都会根据其键值被自动排序,同时set中不允许两个元素有相同的键值。
set的头文件#include <set>
set的声明:
set < type > S; // 创建一个名为S的空set,type是类型名。
set的使用:
插入数据:
s.insert(key_value); /*将key_value插入到set中,返回值是pair<set<int>::iterator, bool>,bool标志着插入是否成功,而 iterator代表插入的位置,若key_value已经在set中,则iterator表示key_value在set中的位置。如果 key_value不存在,则插入;否则不进行任何操作。 */ s.insert(iter, key_value); //在指定的迭代器位置插入key_value,返回该迭代器。 s.insert(begin, end); //将迭代器begin到end之间的元素插入到set中,返回值是void。
查找数据:
s.count(k); /*返回s中键值等于k的元素的个数,这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样 就变成了判断某一键值是否在set出现过了。*/ s.find(k); //如果查找到键值k,则返回该键值的迭代器位置;否则,返回集合最后一个元素后面的一个位置,即end()。
删除数据:
s.erase(key_value); // 删除键值为key_value的值 s.erase(iter); // 删除迭代器iter所指向的元素 s.erase(iterator first, iterator last); // 删除两个迭代器之间的值
set的基本方法:
S.begin(); // 返回set容器的第一个元素。 S.end(); // 返回set容器的最后一个元素的下一个位置。 S.clear(); // 删除set容器中的所有的元素。 S.empty(); // 判断set容器是否为空。 S.max_size(); // 返回set容器可能包含的元素最大个数。 S.size(); // 返回当前set容器中的元素个数。 S.rbegin(); // 返回set容器的最后一个元素。 S.rend(); // 返回set容器的第一个元素的前一个位置。 S.erase(); // 删除迭代器iter所指向的元素
8.STL—string
前言:
string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。我们尽可以把它看成是C++的基本数据类型。
string的头文件#include <string>
string的声明:
string s; // 生成一个空字符串s
string s(str) ; // 拷贝构造函数生成str的复制品
string基本对象操作:
string s; s.empty(); // s为空串 返回true s.size(); // 返回s中字符个数 类型应为:string::size_type s[n]; // 从0开始相当于下标访问 s = s1+s2; // 把s1和s2连接成新串 返回新串 s1=s2; // 把s1替换为s2的副本 s1==s2; // 比较,相等返回true `!=, <, <=, >, >=` //惯有操作 //当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的: string s1(“hello”); string s3=s1+”world”; //合法操作 string s4=”hello”+”world”; //非法操作:两个字符串字面值相加
string的方法:
str.empty(); //判空 str.length(); //字符串长度 str.clear(); //清空字符串 str.find(tmpstr); //在字符串中检索字符串tmpstr是否存在。 str.swap(tmpstr); //交换两个字符串的内容 sort(str.begin(),str.end()); //字符串排序 reverse(str.begin(),str.end()); //字符串反转 to_string(str);//数字转字符串 stoi(str);//字符串转数字 atoi(str.c_str());//字符串转数字
小案例:
string到int的转换:
#include <iostream> #include <algorithm> #include <sstream> #include <string> using namespace std; int main() { int n=0; string result="10000"; stringstream st; st<<result; st>>n; // n等于10000 cout<<(n + 10)<<endl; //运行结果为10010 return 0; }
int到string的转换:
//方法一: #include <iostream> #include <algorithm> #include <sstream> #include <string> using namespace std; int main() { int n = 20210506; string str = ""; stringstream st; st<<n; str = st.str(); cout<<(str + 'A')<<endl; //结果为20210506A return 0; } //方法二: #include <iostream> #include <algorithm> #include <sstream> #include <string> using namespace std; int main() { int n = 20210506; string str = ""; str = to_string(n); cout<<(str + 'A')<<endl; return 0; }
完美撒花!!!