本人使用c++的STL库的一些总结
前言
以下都是个人在使用c++stl的时候容易忘记的一些代码
String的相关测试
//整数转字符串(转入string内)
int a = 10;
string s1;
s1 += to_string(a);
//获取string整一行
string s1;
getline(cin, s1);
//字符转string
char tmp = 2 + 'A';
string ans;
ans.push_back(tmp);
return ans;
//string转int
string s1 = "0001";
int a = stoi(s1);
//string转ll
stoll
//整型转string
string s1;
int a = 100;
s1 = to_string(a);
//把string变成c的字符串,用于判断结束用的
const char* c;
string s = "1234";
c = s.c_str();
//string截断
string s1 = "abcdef";
string a = s1[i].substr(0, 2);//到a到c,c不计在内。左闭右开
string b = s1[i].substr(2);//c到结尾 cdef
//两个string的比较
std::string s1 = "Hello";
std::string s2 = "Hello";
int val = s1.compare(s2);
Map的细节测试
//以下是测试用的两个仿函数
//
struct CountVal//仿函数是结构体,仿函数内容拷贝
{
bool operator()(const pair<string, int>& l, const pair<string, int>& r)//堆种小于是排大堆的,大于是排小堆的
{
//return l.second > r.second;//堆种小于是排大堆的,大于是排小堆的
return l.second < r.second;//小于建大堆,大于建小堆
}
};
struct CountIterVal//仿函数,用迭代器排序的用法
{
bool operator()(const map<string, int>::iterator& l, const map<string, int>::iterator& r)
{
//return l->second > r->second;//堆种小于是排大堆的,大于是排小堆的
return l->second < r->second;
}
};
void map_test1(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
{
countMap[str]++;//普通map用[]可以做到没有的话插入,有的话增加,拿的是map种的value增加
}
// 数据量不大,排序
// sort,用的是普通map的方法
vector<pair<string, int>> sortV;//用一个vector容器装载map中的类容,应为sort要随机迭代器,vector里面存的是pair
for (auto& kv : countMap)
{
sortV.push_back(kv);//往vector容器中插入map的pair
}
//排序
sort(sortV.begin(), sortV.end(), CountVal());//最后一个是匿名对象,仿函数要传匿名对象有(),模板类传参数不用匿名对象
//输出
for (int i = 0; i < k; ++i)
{
cout << sortV[i].first << ":" << sortV[i].second << endl;
}
cout << endl;
}
void map_test2(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;//建立一个map
for (auto& str : fruits)
{
countMap[str]++;//普通map用[]可以做到没有的话插入,有的话增加,拿的是map种的value增加
}
vector<map<string, int>::iterator> sortV;//把countMap的迭代器拷贝到vector中,拷贝的量会少很多
//往sortV中插countMap中的迭代器
auto it = countMap.begin();
while (it != countMap.end())
{
sortV.push_back(it);
++it;
}
//对迭代器中内容解引用找scend然后排序,写了个仿函数
sort(sortV.begin(), sortV.end(), CountIterVal());
for (int i = 0; i < k; ++i)
{
cout << sortV[i]->first << ":" << sortV[i]->second << endl;//如果内部存pair,是个结构提就可以用.来访问,而迭代器是指向pair的指针,只能->来访问
}
cout << endl;
}
void map_test3(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;//建立一个map
for (auto& str : fruits)
{
countMap[str]++;//普通map用[]可以做到没有的话插入,有的话增加,拿的是map种的value增加
}
//multimap中存的是与map相反的kv这样就可以统计次数了,可以存多个相等的k
//greater排降序
multimap < int, string, greater<int>> sortMap;//用multimap排map,这里开可以给sortMap一个greater<int>的防函数参数用于控制排序方式,是参数,所以不用匿名()
for (auto& kv : countMap) //让multimp存的key和value与原来countMap的反着来达到目的
{
sortMap.insert(make_pair(kv.second, kv.first));
}
//auto it= sortMap.rbegin();如果multimap中是less的仿函数那么就用rbegin(),如果是greater就用begin()
auto it= sortMap.begin();
while (k--)
{
cout <<it->first << ":" << it->second << endl;
it++;
}
}
void map_test4(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
{
countMap[str]++;
}
// 堆
//可以反向迭代器取top k(反着走k次),也可以用堆(优先级)队列取top k
//仿函数CountVal找的是second来比较
//大于是小堆,小堆可以找topK,但是这样会该表原来用vector来存的效果,vector中小于就是升序,大于是降序
priority_queue<pair<string, int>, vector<pair<string, int>>, CountVal> pq;
for (auto& kv : countMap)
{
pq.push(kv);
}
while (k--)
{
cout << pq.top().first << ":"<<pq.top().second << endl;
pq.pop();
}
cout << endl;
}
void map_test5(const vector<string>& fruits, size_t k)
{
map<string, int> countMap;
for (auto& str : fruits)
{
countMap[str]++;
}
priority_queue<map<string, int>::iterator, vector<map<string, int>::iterator>, CountIterVal> pq;//类模板传参数,最有一个仿函数是参数,函数模板传参数
auto it = countMap.begin();
while (it != countMap.end())
{
pq.push(it);
++it;
}
while (k--)
{
cout << pq.top()->first << ":" << pq.top()->second << endl;
pq.pop();
}
cout << endl;
}
void map_test6()
{
map<string, string> dict;
pair<string, string> kv1("sort", "排序");//第一种写法
dict.insert(kv1);
//
dict.insert(pair<string, string>("string", "字符串"));//第二种写法
// 自动推到类型
dict.insert(make_pair("test", "测试")); // 使用它,第三种写法
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
while (it != dict.end())//不能用迭代器修改k
{
//it->first = "wess";
//it->second = "wess";
//cout << *it << " ";
//cout << (*it).first << ":" << (*it).second << endl;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
void map_test8()
{
string arr[] = { "苹果", "苹果", "香蕉", "苹果", "香蕉", "苹果", "樱桃" };
map<string, int> countMap;
/*for (auto& str : arr)
{
auto ret = countMap.find(str);//find找到的是中序遍历第一个出现的,也就是这个元素的最左节点
if (ret == countMap.end())
{
countMap.insert(make_pair(str, 1));
}
else
{
ret->second++;
}
}*/
//[]的实现是这样的
//for (auto& str : arr)
//{
// auto kv = countMap.insert(make_pair(str, 1));
// if (kv.second == false)
// {
// kv.first->second++;//这里kv是个pair他的第一个指向的是在map中存在的,前面找的那个元素地址,而这个节点里面又有个pair(及外层piar的first就是这个节点,这个节点再指向second就是水果的个数
// }
//}
for (auto& str : arr)
{
countMap[str]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
void map_test9()
{
map<string, string> dict;
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("left", "左边"));//应为map是k排序,k一样不会管value所以不会插入
dict.insert(make_pair("left", "剩余"));//应为map是k排序,k一样不会管value所以不会插入
//[]返回的是对应k的value的引用
dict["left"] = "剩余"; // 修改
dict["test"]; // 插入
cout << dict["sort"] << endl; // 查找
dict["string"] = "字符串"; // 插入+修改
}
int main()
{
vector<string> v = { "苹果", "苹果", "香蕉", "苹果", "香蕉", "苹果", "樱桃", "哈密瓜", "榴莲", "榴莲", "苹果" };
//多种排序方式
map_test1(v, 3);//(test1用map往vector中深拷贝内容加排序的方式实现topk问题)
map_test2(v, 3);//(test2用map往vector中存map的迭代器(减少拷贝)的方式实现topk问题)
map_test3(v, 3);//(test3用map往multimap反着存kv的方式实现topk问题(但是是深拷贝))
map_test4(v, 3);//(用堆pq的方式深拷贝map的值做排序)
map_test5(v, 3);//(用堆pq但是存迭代器的方式做排序)
map_test6();//(关于map如何插入的问题)
map_test7();//(没写这个函数)//map的earse删除的也是中序遍历的第一个出现的位置,返回这个位置,但是earse(30)就会全部删光
map_test8();//[]号的原理和用处,还有find返回的东西是什么
map_test9()//[]的修改,插入,查找
return 0;
}
SET的相关测试
void test_set1()
{
// 排序+去重
set<int> s;
s.insert(3);
s.insert(1);
s.insert(5);
s.insert(2);
s.insert(8);
s.insert(1);
s.insert(8);
//set<int>::iterator it = s.begin();
auto it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//s.erase(30)如何封装的
set<int>::iterator pos = s.find(30);
if (pos != s.end())
{
// pos必须一个有效位置的迭代器
s.erase(pos);
}
//下面这个就是由两面封装下来的
cout << s.erase(30) << endl;
cout << s.erase(3) << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
void test_multiset()
{
// 排序
multiset<int> s;
s.insert(3);
s.insert(1);
s.insert(5);
s.insert(2);
s.insert(8);
s.insert(1);
s.insert(8);
s.insert(1);
s.insert(1);
auto it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// find 的val有多个值时,返回中序第一个val值所在节点的迭代器
multiset<int>::iterator pos = s.find(8);
while (pos != s.end())
{
cout << *pos << " ";
++pos;
}
cout << endl;
/*pos = s.find(1);
while (pos != s.end() && *pos == 1)
{
auto next = pos;
++next;
s.erase(pos);
pos = next;
}*/
cout << s.erase(1) << endl;//erase返回size_t删除的个数
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
pos = s.find(5);
if (pos != s.end())
{
// 不允许修改,set,map的k都不给修改
//*pos += 10;
}
}
int main()
{
test_set1();
test_multiset();
return 0;
}
总结
STL等相关的使用后续后不断更新,此博客相当于自己的使用记录