STL简单入门
目录
1、选择C++刷算法的理由
- 1.C++速度快(C不是更快么,java太慢了)
- 2.C++有STL(什么是STL)——使用很方便的类库
- 3.如何使用STL进行高效刷算法
- 4.好处:刷算法,学习成本极低
- 5.如何从C到C++(仅基础语法到刷算法程度)
俗话说:磨刀不误砍柴工
不会c++仍然可以做,但是效率低
2、输入输出
C++保留了C的scanf和printf,增加了额外的cin与cout
例子
2.1.C程序中输入输出
int a;
scanf("%d",&a);
printf("%d",a);
2.2.C++输入输出
int a;
cin>>a;
cout<<a;
2.3.连续输入输出变量
int a,b,c;
cin>>a>>b>>c;
cout<<a<<b<<c;
2.4.优雅地换行
cout<<1;
cout<<endl;
cout<<2;
cout<<3<<endl<<endl;
好处:
1.少写了很多东西
2.连续输入输出变量
3.换行优雅
注意:cin、cout比scanf、printf慢,有时候刷算法超时,可能因为使用了cin、cout
输入输出的数量(>1000)特别多,刷算法用cin,cout容易超时
3、STL(Standard Template Library)与algorithm头文件
STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。
algorithm是对容器继承的一些算法函数,辅助刷算法题
sort函数
概念:迭代器——理解为指针
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={2,1,5,0,-1,5,9};
sort(a,a+7);
for(int i=0;i<7;i++)
cout<<a[i]<<" ";
cout<<endl;
system("pause");
return 0;
}
4、STL——string(*)
概念:相当于char*的封装,理解为字符串
4.1.简单使用
/**C中定义字符串以及打印*/
char *ch="asdkajbf";
for(int i=0;ch[i]!='\0';i++) cout<<*(ch+i);
/**C++中*/
string s="ssadaffw";
cout<<s<<endl;
4.2.获取一行字符串
我想获取一行字符串
hello world
C中:
scanf("%s",ch);//1.仅获取一个单词,空格结束 2.ch[100]得设置初始大小
C++中:
string s;
getline(cin,s);//获取一行数据
cout<<s;
4.3.+=运算符
+=对于字符串,字符有效,数字会转为asc码
string s;
s+="hello";
s+=" world";
s+='5';
s+=10;//10对应的asc码是换行
int a=5;//想把a加入字符串
s+=(a+'0');
cout<<s;
4.4.排序(使用algorithm)
string s="5418340";
sort(s.begin(),s.end());
cout<<s;
4.5.erase函数
/**begin是头迭代器,end是尾迭代器*/
string s="5418340";
s.erase(s.begin());//删除第一个
s.erase(--s.end());//删除最后一个
cout<<s;
4.6.substr函数
/**begin是头迭代器,end是尾迭代器*/
string s="5418340";
s=s.substr(1,3);//取418,取索引为1,往后截断3个
s=s.substr(1,-1);//索引为1,截断到最后
cout<<s;
4.7.循环(3种)
1.for循环
string s="5418340";
for(int i=0;i<s.length();i++) cout<<s[i];
2.迭代器
for(string::iterator it=s.begin();it!=s.end();it++) cout<<*it;
3.迭代器化简
for(auto it=s.begin();it!=s.end();it++) cout<<*it;
-
auto的原理就是根据后面的值,来自己推测前面的类型是什么。
-
auto的作用就是为了简化变量初始化,如果这个变量有一个很长很长的初始化类型,就可以用auto代替。
注意点:
-
用auto声明的变量必须初始化(auto是根据后面的值来推测这个变量的类型,如果后面没有值则报错)
-
函数和模板参数不能被声明为auto(原因同上)但是函数内部变量可以
-
因为auto是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid
-
定义在一个auto序列的变量必须始终推导成同一类型
-
4.利用C++ 11新特性for循环
for(auto x:s) cout<<x;
5、STL——vector(*)
概念:vector相当于数组,模板类型相当于存放的内容
1.vector构造
vector<int> v;//定义一个空vector
vector<int> v2(4);//定义一个4个大小的vector,初始为0
vector<int> v3(4,6);//定义一个4个大小的vector,初始为6
vector<int> v{1,2,3,4,5};//定义一个vector,数字为1,2,3,4,5
for(auto x:v3) cout<<x;
for (int i = 0; i < v.size(); i ++) cout << v[i];
2.用at或者[]获取元素
vector<int> v{1,2,3,4,5};
cout<<v[1];//取索引为1的
cout<<v.at(2);//取索引为2的
3.方法
- push_back追加内容
vector<int> v;
v.push_back(5);
v.push_back(5);
v.push_back(5);
v.push_back(5);
v.push_back(6);
for(auto x:v) cout<<x;
reverse(v.begin(),v.end());
二维
vector<vector<bool>> st;
vector<bool> ve;
for (int j = 0; j < cols; j ++)
ve.push_back(false);
for (int i = 0; i < rows; i ++)
st.push_back(ve);
vector<vector<bool>> st(rows, vector<bool>(cols, false));
- resize进行重置大小
v.resize(10);//不赋值默认为0
- erase删除元素,复杂度为O(n)
v.erase(v.begin());//删除第一个元素
v.pop_back(); v.erase(--v.end());//删除最后一个元素
- 获取第一个元素,获取最后一个元素
/**获取第一个元素*/
cout<<v.front();
cout<<v[0];
cout<<*v.begin();
/**获取最后一个元素*/
cout<<v.back();
cout<<v[v.size()-1];//size是获取大小
cout<<*--v.end();
4.排序
第三个参数为比较器,不写默认为less<int>()
vector<int> v{5,1,2,5,4,0,-1};
sort(v.begin(),v.end(),less<int>());//从小到大
sort(v.begin(),v.end(),greater<int>());//从大到小排序
for(auto x:v) cout<<x;
5.循环
vector<int> v{5,1,2,5,4,0,-1};
for(int i=0;i<v.size();i++) cout<<v[i];//for循环
cout<<endl;
for(vector<int>::iterator it=v.begin();it!=v.end();it++) cout<<*it;//迭代器循环
cout<<endl;
for(auto it=v.begin();it!=v.end();it++) cout<<*it;//迭代器简化循环
cout<<endl;
for(auto x:v) cout<<x;//c++11新特性
6、STL——stack(*)
概念:栈
- 构造
stack <int> s;
- push、pop、size、empty
s.push(2);//push 入栈一个元素
s.push(3);
cout<<s.top()<<endl;//返回一个栈顶元素的引用,如果栈为空,返回值未定义
s.pop();//弹出栈顶元素,出栈一个元素,pop无返回值
cout<<s.top()<<endl;
cout<<s.size()<<endl;//size 返回元素个数(即入栈的元素的数量)
//empty():在栈中没有元素的情况下返回 true。
//emplace():用传入的参数调用构造函数,在栈顶生成对象。
//swap(stack<T> & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。
-进制转换(十进制转二进制)
int itob(int decimal){
stack<int> s;int res=0;
while(decimal!=0){
s.push(decimal%2);
decimal/=2;
}
while(!s.empty()){//empty判断栈 是不是为空
res=res*10+s.top();
s.pop();
}
return res;
}
- 逆序单词(sstream)
输入一行字符串,将字符串逆序打印
输入:hello world my name is steve yu
输出:yu steve is name my world hello
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;
int main(){
string str;
stack<string> s;
getline(cin,str);
stringstream ss;
ss<<str;//stringstream 可将整个一行的字符串流入
while(ss>>str)//输出以' '为分界
s.push(str);//即将 hello world.....逐个单词堆入栈中
while(!s.empty()){
cout<<s.top();
s.pop();
if(s.size()!=0) cout<<" ";
}
return 0;
}
- 字符串转数字
1. 方法1:
string s="1234";
int i;
stringstream ss;
ss<<s;
ss>>i;
cout<<i;
2. 方法2:stoi
string s="1234";
int i=stoi(s);//stoi(字符串,起始位置,n进制),将 n 进制的字符串转化为十进制
//stoi(str, 0, 2); 将字符串 str 从 0 位置开始到末尾的 2 进制转换为十进制
cout<<i;
- 数字转字符串
1. 方法1:
int a=1234;
string out;
stringstream ss;
ss<<a;
ss>>out;
cout<<out<<endl;
2. 方法2:(to_string)
int a=1234;
cout<<to_string(a)<<endl;//将数值转化为字符串。返回对应的字符串
7、STL——queue
概念:队列
- 构造
queue<int> q;
- push、back
q.push(5);
q.push(6);
cout<<q.front()<<endl;
q.pop();
cout<<q.front()<<endl;
cout<<q.size()<<endl;
priority_queue
Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,也就是优先队列是大顶堆,队头元素最大。
priority_queue<int> p;
//priority_queue<int, vector<int>, greater<int> >p;实现从小到大,也可自己cmp
p.push(1);
p.push(2);
p.push(8);
p.push(5);
p.push(43);
for(int i=0;i<5;i++){
cout<<p.top()<<" ";
p.pop();
} //结果为43 8 5 2 1
8、STL——map(unordered_map pair)
自动建立Key-value的对应
概念:映射(map为树状表,unorderedmap为哈希表)
- map
map<int,int> m;//有序的,树状结构(底层)
m[6]=3;
m[5]=8;
m[4]=9;
for(auto it=m.begin();it!=m.end();it++)
cout<<it->first<<" "<<it->second<<endl;
for(auto tmp:m){
cout<<tmp.first<<" "<<tmp.second<<endl;
}
- unordered_map
unordered_map<int,int> m;//无序的,速度更快。哈希结构(底层)
m[6]=3;
m[5]=8;
m[4]=9;
for(auto it=m.begin();it!=m.end();it++)
cout<<it->first<<" "<<it->second<<endl;
for(auto tmp:m){
cout<<tmp.first<<" "<<tmp.second<<endl;
}
- pair的用法(map转成vector进行排序)
bool cmp(pair<int,int> a,pair<int,int> b){
return a.first>b.first;//pair的实现是一个结构体,主要的两个成员变量是first second
}
int main(){
unordered_map<int,int> m;//无序的,哈希结构(底层)
m[6]=3;
m[5]=8;
m[4]=9;
vector<pair<int,int>> v(m.begin(),m.end());
sort(v.begin(),v.end(),cmp);
for(auto tmp:v){
cout<<tmp.first<<tmp.second<<endl;
}
return 0;
}
9、set(unordered_set)
概念:集合
- 应用计数、去重
set<int> s;//树状结构,有序
unordered_set<int> s2;//哈希结构,无序,快
s.insert(3);
s.insert(4);
s.insert(4);
s.insert(4);
cout<<s.size()<<endl;//结果为2
for(auto tmp:s)
cout<<tmp<<" ";//结果为3,4
cout<<endl;
for(auto it=s.begin();it!=s.end();it++)
cout<<*it<<" ";//结果为3,4
s.find(x) != s.end(); set中已有x元素
cout<<endl;
10、STL——deque
概念:双端队列
deque<int> d;
// 4 9 1 2
d.push_back(1);//从尾插入
d.push_back(2);
d.push_front(9);//从头插入
d.push_front(4);
d.pop_back();//从尾部删除
d.pop_front();//从头删除
for(auto tmp:d) cout<<tmp<<endl;
for(auto it=d.begin();it!=d.end();it++) cout<<*it<<endl;
-
排序
sort(d.begin(),d.end(),greater<int>());//从大到小
11、STL——list
概念:双向链表
list<int> li;
li.push_back(6);
li.push_front(5);
li.emplace_front(9);
li.emplace_back(10);
li.insert(++li.begin(),2);
for(auto tmp:li) cout<<tmp<<endl;
for(auto it=li.begin();it!=li.end();it++) cout<<*it<<endl;
11、multist
cin >> x;
multiset<int>h; //建立一个multiset类型,变量名是h,h序列里面存的是int类型,初始h为空
while(x!=0){
h.insert(x); //将x插入h中
cin >> x;
}
while(!h.empty()){ // 序列非空 h.empty()==true时 表示h已经空了
__typeof(h.begin()) c=h.begin();
//c指向h序列中第一个元素的地址,第一个元素是最小的元素
cout << *c << " "; //将地址c存的数据输出
h.erase(c); //从h序列中将c指向的元素删除
}
12.推荐stl文档
英文:
http://www.cplusplus.com/reference/stl/
中文:
http://c.biancheng.net/stl/