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;
posted @ 2020-10-09 21:57  孔胡子  阅读(1212)  评论(0编辑  收藏  举报