c++ 集合操作
map
添加
map<int, int> my;
my.insert(make_pair(1, 5)); // 如果 key 存在,则添加失败。返回 pair 如下折叠代码块
my[6] = 7; // 如果 key 存在,则更新
my.insert({ 7,8 });
折叠代码块
map
my; my.insert(make_pair(1, 5)); map my; my.insert(make_pair(1, 5));
// insert 返回值为 pair.
pair<map<int, int>::iterator, bool> result = my.insert(make_pair(6, 2)); // 或者 make_pair(1,6)
if(!result.second)
{
cout << "error" << result.first->first << ' ' << result.first->second;
}
else
{
result.first++; // map 自动排序, 测试返回的是插入的位置
if (result.first == my.end())
cout << "success 且插在末位" ;
else
cout << "success 插入成功, 不是末尾";
}
遍历
map<int, int> my;
my.insert(make_pair(1, 5));
for (map<int, int>::iterator item = my.begin(); item != my.end(); item++)
cout << item->first << item->second << endl; // item 是个 pair, 不同于顺序列表可以 *item.first
for (auto& item : my)
{
cout << item.first << item.second;
}
只有顺序容器vector可以 iterator+n, map等关联容器只能 iterator++/iterator--
删除与取值、修改
map<int, int> my;
my.insert(make_pair(1, 5));
my[1] = 99;
cout << my[1] << endl; // 99
my.erase(1); // 单一删除
cout << my.size();
my.clear(); // 全部清空
find 查找
map<int, int> my;
my.insert(make_pair(1, 5));
if (my.find(1) != my.end()) // 找到,返回值位置. 找不到,返回位置为 end
cout << my[1] << endl;
if (my.find(5) == my.end())
cout << "无" << endl;
count 查找
1 if the container contains an element whose key is equivalent to k, or zero otherwise.
int result = my.count(1);
int result2 = my.count(2);
cout << result << result2;
返回查找到的 key 个数。因为 key 为唯一,所以只能为 0 or 1
Set
删除
void erase (iterator position);
size_type erase (const value_type& val); # 指定 value
void erase (iterator first, iterator last);
可以选择通过迭代器或者指定值进行删除。(multiset 同样是这三个函数)
第二种方式返回被删除的个数。set 中因为键唯一,所以无非 0 1
multiset 因为可以存多个相同的值,所以返回值为 “被删除相应的值的个数”
添加
返回值为 pair 类型, pair::first 是插入的返回位置,pair::second 为 bool 类型,代表是否 insert 成功。
set<int> my;
// 方式一
my.insert(4);
pair<set<int>::iterator, bool> result = my.insert(4);
if (!result.second)
cout << "insert error" << endl;
// 方式二
vector<int> myv = { 9,9,10,4 };
my.insert(myv.begin(), myv.end());
for (auto& item : my)
{
cout << item;
}
count find 查找, erase, 遍历
同上文 map 一致, 不再赘述
vector
初始化
// 常用初始化方式
vector<int> my(7, 3); // 7 个三
vector<bool> my2(7, false);
vector<int> my3({ 1,2,8,9 }); // 直接赋值 1 2 8 9
vector<int> my4(my3.begin(), my3.end());
插入
vector<int> my;
my.push_back(5); // 常用
my.emplace_back(6);// 意义同上, 效率更高
my.insert(my.begin() + 1, 8); // 5 8 6 指定位置插入
删除
vector<int> my{4,6,7,8};
my.pop_back(); // 删除末尾
my.erase(my.begin() + 1);// 4 7 指定位置删除
遍历
vector<int> my3({ 1,2,8,9 }); // 直接赋值 1 2 8 9
// 方式1
for (vector<int>::iterator item = my3.begin(); item != my3.end(); item++) // 且可以 item+=2. map关联迭代器不可
cout << *item; // 与map的迭代器不同
// 方式2
for (auto& item : my3)
{
cout << item << ' ';
}
find
这个和关联同期不一样, 并不属于 vector,是专门的函数
template<class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val)
{
while (first!=last) {
if (*first==val) return first;
++first;
}
return last;
}
传入三个参数,1、2为迭代器位置(查找范围),第3个参数为目标值.【返回迭代器位置,所以可以判断是否找到了】
vector<int> my{4,6,7,8,9};
vector<int>::iterator result = find(my.begin(), my.end(), 10);
if (result != my.end())
{
cout << "success 且 idx=" << result - my.begin();
}
else
cout << "无";
find_if
其实看一下模板内容就发现和 find 很一致,只不过更灵活
template<class InputIterator, class UnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)) return first;
++first;
}
return last;
}
可以看到 pred(*first) 所以,也就是找第一个返回 pred 自定义函数的 iterator 位置 【头文件 algorithm】
#include <algorithm> // std::find_if
using namespace std;
bool IsOdd(int i) {
return ((i % 2) == 1);
}
int main()
{
vector<int> my{4,6,7,8,9};
vector<int>::iterator result = find_if(my.begin(), my.end(), IsOdd);
if (result != my.end())
{
cout << "success 且 idx=" << result - my.begin();
}
else
cout << "无";
return 0;
reverse
vector<int> my{4,6,7,9};
reverse(my.begin(), my.end());
string
构造方法
传入【string】
// default
string();
// copy
string (const string& str);
传入【字符串常量】
// substring
string (const char* s, size_t n);
// 323a
string str2("323aa", 4); // 截取前四位
// ca
string str3("32acab", 3, 2); // 第3位开始截取2位
// from c-string
string (const char* s);
// heeee
string str("heeee");
传入【字符】
// fill
string (size_t n, char c); 【注意是数字在前, char 在后】
// aaaaaa
string str0(6, 'a'); // 赋值6份
访问、截取
string str2("323aa");
cout << str2[0] << endl; // 下标访问
cout << str2.substr(2, 3); // 从下标2开始截取3个
cout << str2.size() << str2.length();
插入 insert append
string str("323aa");
str.append("tyui");
str.insert(1, "插入"); // 3插入23aatyui
cout << str;
// str.insert(0, 5,'x'); 在[0] 插入 5 个 'x'
查找 find
看一下函数定义
// 返回无符号整数类型
string::size_t find (const string& str, size_t pos = 0) const;
这是 string 的内置函数,用于查找 str,pos 为起始查找位置【默认为0】,【返回结果】为查找到的第一个下标位置,没找到返回 string::npos. 被定义成无符号数-1,但别使用-1来判断,用string::npos
string s("jk1a2b3c4d5e6f7jkg8h9i1a2b3c4d5e6f7g8ha9i");
string::size_type position;
//find 函数 返回jk 在s 中的下标位置
position = s.find("jk");
//position = s.find("jk", 5);
if (position != s.npos)
cout << position;
else
cout << "No found";
例子:找指定字符串
string s("jk1a2b3c4d5e6f7jkg8h9i1a2b3c4d5e6f7g8ha9i*");
string str = "9i";
string::size_type position = 0;
while ((position = s.find(str, position)) != string::npos) // 每次从 position 起始开始寻找
{
cout << position << ' '; // 输出:20 39
position += 1;
}
rfind 反向查找
和迭代器的 rbegin rend 一样,从末尾开始查找,返回第一个查找到的下标。
string s("jk1a2b3c4d5e6f7jkg8h9i1a2b3c4d5e6f7g8ha9i*");
string str = "9i";
string::size_type position = s.rfind(str);
cout << position; // 输出 39
同理,找不到的判断
string::size_type position = s.rfind(str);
if (position == string::npos)
{
cout << "no found";
}
更多用法:https://www.cnblogs.com/wkfvawl/p/9429128.html
替换 replace
使用方式繁杂,我列一个最常用的: 替换 str pos 位置长度为 len,替换为 str_new。我们可以改造成替换string指定字符
string& replace (size_t pos, size_t len, const string& str);
// 替换 is 为 |ohh|
string line = "this@ is@ a test string!";
string::size_type position = 0;
while ((position = line.find("is", position)) != string::npos)
{
line.replace(position, 2, "|ohh|"); // pos len str_replace
//position++; //注意,因为不是查找,所以肯定每次都从 0 位置开始find
}
cout << line; // 输出:th|ohh|@ |ohh|@ a test string!
find更多用法:
1.https://blog.csdn.net/jiary5201314/article/details/52502516
2.https://www.cnblogs.com/zpcdbky/p/4471454.html
去掉所有空格
// 删除所有空格
string line = " this@ is@ a test string! ";
string::size_type position = 0;
string target = " ";
string replace_ = "";
while ((position = line.find(target, position)) != string::npos)
{
line.replace(position, 1, replace_); // pos len str_replace
//position++; //注意,因为不是查找,所以肯定每次都从 0 位置开始find
}
cout << line;
删除首尾空格
// 去掉首尾空格
string line = " this@ is@ a test string! ";
string::size_type position = 0;
line.erase(position, line.find_first_not_of(' '));
line.erase(line.find_last_not_of(' ') + 1, line.size()); // 注意+1,否则 !被删除了
cout << line;
tuple
创建、取值、修改
tuple<int, int, string> my = make_tuple(3, 4, "sys");
tuple<int, int, string> my2(3, 4, "sys");
get<1>(my) = 99;
cout << get<1>(my) << get<2>(my); // 99 sys
pair
创建、取值、修改
// 创建
pair <std::string, double> product2("tomatoes", 2.30);
pair <std::string, double> product3(product2);
pair <std::string, double> product1 = make_pair(string("lightbulbs"), 0.99);
// 修改
product1.first = string("ohhhh");
// 取值
cout << product1.first << product1.second;