11.1 C++ STL 应用字典与列表
C++ STL 标准模板库提供了丰富的容器和算法,这些模板可以灵活组合使用,以满足不同场景下的需求。本章内容将对前面学习的知识进行总结,并重点讲解如何灵活使用STL中的vector和map容器,以及如何结合不同的算法进行组合。
通过灵活组合使用这些容器和算法,能够满足不同场景下的需求,实现高效的数据处理和操作。STL的设计思想是将数据结构和算法进行分离,使得开发者能够更加专注于解决问题,提高了代码的可读性和可维护性。因此,掌握STL的使用技巧对于C++程序员来说是非常重要的。
11.1 字典拆分为列表
此代码创建了一个std::map
容器,将一些测试数据插入到容器中,然后通过迭代器遍历该容器,并将key
和value
分别插入到vector
容器中,形成两个列表。
最后,分别将这两个列表打印出来。该代码的核心功能是将一个std::map
容器转换成两个vector
容器,同时输出两个vector
容器的内容,以此实现了std::map
的分离操作。
- 功能概述:将
map
字典拆分为vect_key
和vect_value
两个Vector
列表
#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
std::map<long, std::string> map;
// 插入测试数据
map.insert(std::pair<long, std::string>(1001, "administrator"));
map.insert(std::pair<long, std::string>(1002, "root"));
map.insert(std::pair<long, std::string>(1003, "lyshark"));
// 将字典拆分为列表
std::vector<long> vect_key;
std::vector<std::string> vect_value;
for (std::map<long, std::string>::iterator it = map.begin(); it != map.end(); it++)
{
// 分别将key和value插入到列表
vect_key.push_back(it->first);
vect_value.push_back(it->second);
}
// 输出分割结果
for (int x = 0; x < vect_key.size(); x++)
std::cout << "Key: " << vect_key[x] << std::endl;
for (int x = 0; x < vect_value.size(); x++)
std::cout << "Value: " << vect_value[x] << std::endl;
std::system("pause");
return 0;
}
11.2 列表合并为字典
该代码创建了两个std::vector
容器,分别包含一些测试数据,并将这两个容器的元素通过循环方式逐一插入到一个std::map
容器中。最后,通过迭代器输出std::map
容器中所有的键值对。
该代码的核心功能是将两个std::vector
容器的元素分别对应地插入到一个std::map
容器中,并将最终的结果进行打印输出。
- 功能概述:将两个列表
vect_key
和vect_value
通过循环合并为一个std::map
字典
#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
// 定义列表并追加元素
std::vector<long> vect_key;
std::vector<std::string> vect_value;
vect_key.push_back(1001);
vect_key.push_back(1002);
vect_key.push_back(1003);
vect_value.push_back("administrator");
vect_value.push_back("root");
vect_value.push_back("lyshark");
// 将列表依次插入到map容器
std::map<long, std::string> map;
// 先来判断两个列表是否一致
if (vect_key.size() == vect_value.size())
{
// 循环插入到map容器
for (int x = 0; x < vect_key.size(); x++)
{
map.insert(std::pair<long, std::string>(vect_key[x], vect_value[x]));
}
}
// 输出插入后的map容器
for (std::map<long, std::string>::iterator it = map.begin(); it != map.end(); it++)
{
std::cout << "Key: " << it->first << " | Value: " << it->second << std::endl;
}
std::system("pause");
return 0;
}
11.3 根据字典键降序排序
该代码创建了一个std::map
容器,其中std::string
是key
,int
是value
。通过指定greater<string>
进行降序排列。该程序接着给容器对象添加多个键值对,其中包括使用insert()
函数和数组索引语法添加键值对。
最后,该程序使用迭代器循环遍历map
容器,将所有键值对按照key
的降序依次输出。该代码的核心功能是创建一个带有某种关键字类型的std::map
容器,并实现基本的添加数据和遍历数据的操作。
- 提示:MAP字典第三个参数不指定则按照升序排列,如果指定了
greater<string>
则会按照降序排列
#include <iostream>
#include <functional>
#include <string>
#include <map>
using namespace std;
int main(int argc, char *argv[])
{
// map第三个参数greater<string>其中的string指定的是map中key的值.
std::map<std::string, int, greater<string>> map;
std::map<std::string, int, greater<string>>::iterator iter;
map["aa"] = 90;
map["bbb"] = 95;
map["cccc"] = 100;
map.insert(map<string, int>::value_type("ddddd", 88));
for (iter = map.begin(); iter != map.end(); iter++)
{
std::cout << "key: " << iter->first << " Value: " << iter->second << std::endl;
}
std::system("pause");
return 0;
}
11.4 根据字典键长度排序
该段代码创建了一个std::map
容器,其中key
是std::string
类型value
是int
类型。为实现按照key
长度进行排序,需要额外定义一个key_string_cmp
的结构体,该结构体要重载()
运算符以实现比较大小的功能。
接着,程序添加多个字符串类型的键值对到map
容器中,其中包括使用数组索引语法以及使用insert()
函数添加键值对。最后,程序使用迭代器循环输出map
容器的所有键值对,注意此时输出的键值对已经按照key
长度排好序了。
该代码的核心功能是创建一个针对字符串类型key
的std::map
容器,并按照key
长度进行排序,然后实现基本的添加数据和输出数据的功能。其中自定义排序需要我们定义key_string_cmp
排序结构,并将其传递到map
字典的第三个参数上即可。
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct key_string_cmp
{
bool operator() (const string& x, const string& y)
{
return x.length() < y.length();
}
};
int main(int argc, char *argv[])
{
// 针对字符串类型Key的排序
std::map<std::string, int, key_string_cmp > string_map;
std::map<std::string, int, key_string_cmp >::iterator string_iter;
string_map["aaaa"] = 90;
string_map["bb"] = 95;
string_map["ccccc"] = 100;
string_map["d"] = 24;
for (string_iter = string_map.begin(); string_iter != string_map.end(); string_iter++)
{
std::cout << "key: " << string_iter->first << " Value: " << string_iter->second << std::endl;
}
std::system("pause");
return 0;
}
11.5 根据字典值排序
该代码创建了一个std::map
容器,其中key
是std::string
类型value
是int
类型。程序使用数组索引语法添加多个键值对。接着,该程序将map
容器中的数据取出来,放入到vector
容器中,实现了将std::map
转换为std::vector
的功能。
接下来,程序使用sort()
函数对转换为vector
结构的序列进行排序,此处使用的是value_cmp
结构体对value
进行排序。最后,该程序输出排序后的vector
容器的内容,此处输出的是key
和value
,且是按照value
从小到大的顺序输出。
该代码的核心功能是将一个std::map
容器转换为std::vector
容器,并按照某种规则对该vector
进行排序,以此实现对std::map
中数据的排序功能。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
typedef pair<string, int> PAIR;
struct value_cmp
{
bool operator() (const PAIR& P1, const PAIR& P2)
{
return P1.second < P2.second;
}
};
int main(int argc, char *argv[])
{
std::map<std::string, int> map;
std::map<std::string, int>::iterator iter;
map["admin"] = 90;
map["root"] = 95;
map["lyshark"] = 100;
// 将map容器中的数据取出来,放入到Vector
vector<PAIR>vect;
for (iter = map.begin(); iter != map.end(); iter++)
{
vect.push_back(*iter);
}
// 对转换为Vector结构的序列进行排序,此处使用value_cmp()
sort(vect.begin(), vect.end(), value_cmp());
// 输出排序后的Vector结构
for (int x = 0; x < vect.size(); x++)
{
std::cout << "输出Key: " << vect[x].first << std::endl;
std::cout << "输出Value: " << vect[x].second << std::endl;
}
std::system("pause");
return 0;
}
11.6 根据字典键返回值
该代码创建了一个std::map
容器,其中key
是std::string
类型,value
是int
类型。程序使用数组索引语法添加多个键值对。
该程序实现了两种查找功能:
- 非函数版寻找:使用
find()
函数根据key
查找相应的value
,如果查找到就输出值 - 在函数版寻找:使用
get_value()
函数根据key
查找相应的value
,并返回该值,如果找不到则返回0
最后,该程序输出找到的value
。需要注意的是,两种方式都可以寻找相应的值。
该代码的核心功能是实现根据key
在std::map
容器中查找对应的值并输出结果。其中,采用了两种查找方式,一种是使用map
自带的find()
函数,另一种是通过定义一个函数实现的查找功能。
#include <iostream>
#include <functional>
#include <string>
#include <map>
using namespace std;
// 根据Key寻找Value并返回
int get_value(std::map<std::string,int> ptr, std::string key)
{
std::map<std::string, int>::iterator iter;
iter = ptr.find(key);
if (iter != ptr.end())
{
// std::cout << iter->second << std::endl;
return iter->second;
}
return 0;
}
int main(int argc, char *argv[])
{
std::map<std::string, int> map;
std::map<std::string, int>::iterator iter;
map["admin"] = 90;
map["root"] = 95;
map["lyshark"] = 100;
// 非函数版寻找
iter = map.find("lyshark");
if (iter != map.end())
{
std::cout << "找到数值: " << iter->second << std::endl;
}
// 函数版寻找
int ref_value = get_value(map, "root");
std::cout << "找到数值: " << ref_value << std::endl;
std::system("pause");
return 0;
}
11.7 根据字典值寻找键
该段代码创建了一个std::map
容器,其中key
是int
类型value
是std::string
类型。程序使用insert()
函数向map
容器中添加了多个元素。
该程序实现了两种查找功能:未封装的查找与封装函数版查找。在未封装的查找中,使用find_if()
函数根据value
完成查找;在封装函数版查找中,通过定义一个类map_value_finder
实现find_if()
函数。
最后,该程序输出找到的key
和value
。需要注意的是,两种方式都可以寻找相应的key
和value
。
该代码的核心功能是实现根据value
在std::map
容器中查找相应的key
和value
,并输出结果。其中,采用了两种查找方式,一种是使用find_if()
函数,另一种是通过定义一个类封装实现的查找功能。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// 定义查找方法
class map_value_finder
{
public:
map_value_finder(const std::string &cmp_string) :m_s_cmp_string(cmp_string){}
bool operator ()(const std::map<int, std::string>::value_type &pair)
{
return pair.second == m_s_cmp_string;
}
private:
const std::string &m_s_cmp_string;
};
// 函数版根据Map的Value寻找key
std::pair < int, std::string > get_item(std::map<int,std::string> ptr, std::string value)
{
std::map < int, std::string >::iterator it = ptr.end();
// 根据传入的value寻找字典匹配数据
it = std::find_if(ptr.begin(), ptr.end(), map_value_finder(value));
// 无论是否找到都需要返回一个对组
std::pair < int, std::string > ref_pair;
if (it == ptr.end())
{
// 如果没找到直接返回空的对组
ref_pair = std::make_pair(0, "None");
return ref_pair;
}
else
{
ref_pair = std::make_pair(it->first, it->second);
return ref_pair;
}
}
int main(int argc,char * argv[])
{
std::map<int, std::string> map;
map.insert(std::make_pair(10, "china"));
map.insert(std::make_pair(20, "usa"));
map.insert(std::make_pair(30, "english"));
map.insert(std::make_pair(40, "hongkong"));
// 未封装的查找
std::map<int, std::string>::iterator it = map.end();
it = std::find_if(map.begin(), map.end(), map_value_finder("usa"));
if (it == map.end())
{
std::cout << "没找到.." << std::endl;
}
else
{
std::cout << "找到的Key: " << it->first << " 找到的Value: " << it->second.c_str() << std::endl;
}
// 封装函数版查找
std::pair<int, std::string> ref = get_item(map, "english");
std::cout << "找到的Key: " << ref.first << " 找到的Value: " << ref.second << std::endl;
std::system("pause");
return 0;
}
11.8 寻找列表中相同元素
这段代码演示了两种查找算法find()
和find_first_of()
,实现了寻找两个列表中第一次出现在第二个容器中的元素。
- 第一种查找算法,使用
find()
函数在vector
容器中查找特定元素,如果查找成功,则输出元素在容器中的位置(下标)。注意,该函数仅查找序列中的第一个符合条件的元素。 - 第二种查找算法,使用
find_first_of()
函数在两个vector
容器之间查找相同元素,如果查找成功,则输出该元素及其位置。注意,该函数查找的是两个序列中第一个相同的元素,而不是整个序列中相同的元素。
此外,该程序还定义了一个函数test_find_if()
,用于在vector
容器中查找满足特定条件的元素,如果查找成功,则输出该元素及其位置(下标)。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// 使用自定义函数
bool MyFunction(int x)
{
if (x >= 9)
return 1;
else
return 0;
}
// 遍历时增加过滤条件
void test_find_if(vector<int> ptr)
{
vector<int>::iterator iter;
iter = find_if(ptr.begin(), ptr.end(), MyFunction);
if (iter != ptr.end())
{
cout << "满足条件的数: " << *iter << " 下标: " << iter - ptr.begin() << endl;
}
}
// 查找两个数组相同部分
void test_find_first_of(std::vector<int> VectA,std::vector<int> VectB)
{
vector<int>::iterator iter;
iter = find_first_of(VectA.begin(), VectA.end(), VectB.begin(), VectB.end());
if (iter != VectA.end() || iter != VectB.end())
{
cout << "第一次出现在第二个容器中的元素为: " << *iter << " 下标: " << iter - VectA.begin() << endl;
}
else
{
cout << "两个容器没有相同元素" << endl;
}
}
int main(int argc,char * argv[])
{
// 通过元素值,寻找下标
std::vector<int> vect = { 1, 5, 6, 7, 8, 9, 0, 3, 2, 1 };
std::vector<int>::iterator iter;
iter = find(vect.begin(), vect.end(), 7);
if (iter != vect.end())
{
std::cout << "找到元素下标: " << distance(vect.begin(), iter) << std::endl;
}
test_find_if(vect);
// 寻找两个列表中的相同元素
std::vector<int> VectA = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
std::vector<int> VectB = { 5, 6, 7, 8, 9, 4, 32, 6, 8, 9 };
test_find_first_of(VectA, VectB);
std::system("pause");
return 0;
}
11.9 查找列表中的交集
这段代码实现了一个函数get_vect_value_list()
,可以查找两个vector
容器中相同的元素,并将这些元素放入一个新的vector
容器中并返回。在具体实现中,使用了STL中的find()
函数来查找相同的元素,并通过push_back()
函数将查找到的元素添加到新的vector
容器中。
在主函数中,定义两个vector
容器VectA
和VectB
,并使用get_vect_value_list()
函数获取两个vector
中相同的元素,并将其赋值给item
。最后使用for循环遍历返回两者的交集列表。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// 查询两个列表中相同的元素,并返回一个列表
std::vector<int> get_vect_value_list(std::vector<int> VectA, std::vector<int> VectB)
{
std::vector<int> item = {};
std::vector<int>::iterator iter;
// 两个列表必须一致
if (VectA.size() == VectB.size())
{
for (int x = 0; x < VectA.size(); x++)
{
iter = find(VectB.begin(), VectB.end(), VectA[x]);
if (iter != VectB.end())
{
// 找到后加入到item
item.push_back(*iter);
}
}
}
return item;
}
int main(int argc,char * argv[])
{
std::vector<int> VectA = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
std::vector<int> VectB = { 5, 6, 7, 8, 9, 4, 32, 6, 8, 9 };
// 寻找元素
std::vector<int> item = get_vect_value_list(VectA, VectB);
for (int x = 0; x < item.size(); x++)
{
std::cout << "A中元素与B中都存在的: " << item[x] << std::endl;
}
std::system("pause");
return 0;
}
11.10 根据键设置字典值
在本程序中,定义了两个函数set_dict_value()
和get_dict_value()
,分别用于设置和获取map
容器中指定key
的value
。在具体实现中,使用STL中的find()
函数来查找指定key的位置,然后通过修改该位置对应的value 的值来实现修改操作;另外,使用该函数还可以避免在添加元素时出现重复的键值对。
在主函数中,先使用insert()
函数向map容器中添加若干键值对;然后使用set_dict_value()
函数将key为1的值修改为1000;接着使用get_dict_value()
函数获取key为3的值;最后使用for循环遍历map容器中的所有键值对,并输出键和值。
读者需要注意,map容器的键和值可以是任意类型,而且键必须是没有重复值的,因为map是依靠键来查找值的。
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
// 设置指定key中的value
bool set_dict_value(std::map<int, int>& ptr, int find_key, int set_value)
{
std::map<int, int>::iterator iter;
// find_key 寻找key
iter = ptr.find(find_key);
if (iter != ptr.end())
{
// 替换value
iter->second = set_value;
return true;
}
return false;
}
// 根据find_key获取到字典的value,并返回
int get_dict_value(std::map<int, int>& ptr, int find_key)
{
std::map<int, int>::iterator iter;
// find_key 寻找key
iter = ptr.find(find_key);
if (iter != ptr.end())
{
// 返回当前值
return iter->second;
}
return false;
}
int main(int argc, char * argv[])
{
std::map<int, int> map;
// 增加记录
map.insert(std::pair<int, int>(1, 100));
map.insert(std::pair<int, int>(2, 200));
map.insert(std::pair<int, int>(3, 300));
map.insert(std::pair<int, int>(4, 400));
// 将map中的key=1 的value的值设置为 1000
bool ref = set_dict_value(map, 1, 1000);
std::cout << "设置状态: " << ref << std::endl;
// 获取特定key的value值
int _value = get_dict_value(map, 3);
std::cout << "获取数据: " << _value << std::endl;
// 输出设置后的状态
for (std::map<int, int>::iterator ptr = map.begin(); ptr != map.end(); ptr++)
{
std::cout << "Key: " << ptr->first << " Value: " << ptr->second << std::endl;
}
std::system("pause");
return 0;
}
11.11 实现列表容器计数
这段代码实现了统计一个vector
容器中各个元素出现次数的功能。在具体实现中,使用map
容器来保存元素及其出现次数的对应关系。对于每个元素,先使用count()
函数查找其在map
容器中的出现次数,如果不是第一次出现,则从map
容器中取出其出现次数后递增,再将修改后的次数更新回map
容器;否则,将其次数设置为1。最后,使用for
循环遍历map
容器,并输出元素及其出现次数。
读者需要注意,这段代码中使用了STL中的operator[]
,该运算符在map容器中可以用来访问指定键的值,同时也可以用于添加新的键值对。另外,需要注意count()
函数的返回值类型是size_t
,因此不能和int
类型的变量直接比较大小。
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
// 设置指定key中的value
bool set_dict_value(std::map<int, int>& ptr, int set_key, int set_value)
{
ptr[set_key] = set_value;
return true;
}
// 根据find_key获取到字典的value,并返回
int get_dict_value(std::map<int, int>& ptr, int find_key)
{
std::map<int, int>::iterator iter;
iter = ptr.find(find_key);
if (iter != ptr.end())
{
return iter->second;
}
return false;
}
int main(int argc, char * argv[])
{
std::map<int, int> map;
std::vector<int> vect = { 54, 66, 78, 34, 44, 44, 56, 3, 4, 56, 7, 89, 7, 5, 34, 4, 56, 7, 8, 90, 0, 8, 6, 4, 3 };
for (int x = 0; x < vect.size(); x++)
{
// 寻找map中是否存在列表中的特定元素
int ref = map.count(vect[x]);
if (ref != 0)
{
// 不是第一次则,先取出原值,递增后,在回写.
int _value = get_dict_value(map, vect[x]);
_value = _value + 1;
set_dict_value(map, vect[x], _value);
}
else
{
// 如果是第一次找到,直接设置为1
set_dict_value(map, vect[x], 1);
}
}
// 输出计数器
for (std::map<int, int>::iterator iter = map.begin(); iter != map.end(); iter++)
{
std::cout << "数字: " << iter->first << " --> 出现次数: " << iter->second << std::endl;
}
std::system("pause");
return 0;
}
11.12 验证两个列表异同点
这段代码演示了如何比较两个vector
容器之间的差异。先定义了两个函数,分别为find_vector_value()
和get_list_value_list()
。
find_vector_value() 函数用于检查某个元素是否存在于vector
容器中。具体实现中,使用STL中的find()
函数来查找指定元素的位置,如果该元素存在于容器中,则返回 true;否则返回 false。
get_list_value_list() 函数用于比较两个vector
容器之间的差异。具体实现中,先判断两个容器的长度是否相等,如果不相等则直接返回false。否则,对于vectorA
容器中的每个元素,都调用find_vector_value()
函数查找其是否存在于vectorB
容器中;如果存在,则将该元素添加到result_identical
容器中,否则,将其添加到result_different
容器中。最后,该函数返回true,表示执行成功。
在主函数中,先定义了两个vector
容器x
和y
,然后调用get_list_value_list()
函数,将x
和y
之间的差异分别存储在名为identical
和different
的容器中。最后,使用for
循环遍历这两个容器,并输出它们所包含的元素。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// 寻找特定元素是否存在于列表中
bool find_vector_value(std::vector<int> ptr, int find_value)
{
std::vector<int>::iterator iter;
if (ptr.size() >= 0)
{
for (int x = 0; x < ptr.size(); x++)
{
iter = find(ptr.begin(), ptr.end(), find_value);
if (iter != ptr.end())
{
return true;
}
}
}
return false;
}
// 传入两个列表,返回 result_identical = 相同 / result_different = 不同
bool get_list_value_list(std::vector<int> vect_a, std::vector<int> vect_b, std::vector<int>& result_identical, std::vector<int>& result_different)
{
std::vector<int>::iterator iter;
// 如果两个列表相同,则我们以第一个列表作为循环变量
if (vect_a.size() == vect_b.size())
{
for (int x = 0; x < vect_a.size(); x++)
{
// 验证vect_b 里面是否存在vect_a中的特定元素
bool ref = find_vector_value(vect_b, vect_a[x]);
if (ref == true)
{
result_identical.push_back(vect_a[x]);
}
else if (ref != true)
{
result_different.push_back(vect_a[x]);
}
}
return true;
}
return false;
}
int main(int argc,char * argv[])
{
std::vector<int> x = { 23, 56, 55, 43, 7, 8, 9, 0, 5, 4, 6, 7, 8, 9, 4 };
std::vector<int> y = { 23, 56, 55, 334, 7, 8, 9, 0, 5, 4, 6, 7, 8, 9, 4 };
// identical 存放两者都有的 / different 存放两者都没有的
std::vector<int> identical;
std::vector<int> different;
get_list_value_list(x, y, identical, different);
for (int x = 0; x < identical.size(); x++)
{
std::cout << "x中存在的元素: " << identical[x] << std::endl;
}
for (int x = 0; x < different.size(); x++)
{
std::cout << "x中不存在的元素: " << different[x] << std::endl;
}
std::system("pause");
return 0;
}
11.13 实现两个列表合并
这段代码实现了将两个vector
容器中的元素进行合并的功能。具体实现中,使用extend_vector_list()
函数来实现。
extend_vector_list() 函数用于合并两个vector
容器中的元素。该函数有三个参数,分别为vect_x、vect_y
和ignore
。其中,vect_x
和vect_y
分别表示要进行合并的两个vector
容器;ignore 参数表示是否忽略重复元素,如果为 true,则在合并过程中会自动去重,否则会保留重复元素。
具体实现中,先将vect_x
中的所有元素添加到item
容器中,然后将vect_y
中的所有元素依次逐个进行查找,根据ignore
参数的不同处理方式,对于不存在于item
容器中的元素,将其添加到item
容器中。最后,该函数返回item
容器,表示执行成功。
在主函数中,先定义了两个要合并的vector
容器x
和y
,然后调用extend_vector_list()
函数进行合并。因为ignore
参数设置为 true,所以在合并过程中会自动去除重复元素。最后使用for循环遍历合并后的vect
容器,并输出它们所包含的元素。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
// 寻找特定元素是否存在于列表中
bool find_vector_value(std::vector<int> ptr, int find_value)
{
std::vector<int>::iterator iter;
if (ptr.size() >= 0)
{
for (int x = 0; x < ptr.size(); x++)
{
iter = find(ptr.begin(), ptr.end(), find_value);
if (iter != ptr.end())
{
return true;
}
}
}
return false;
}
// 合并两个列表元素
std::vector<int> extend_vector_list(std::vector<int> &vect_x, std::vector<int> &vect_y, bool ignore = false)
{
std::vector<int> item;
// 循环现将vect_x 赋值给item
for (int x = 0; x < vect_x.size(); x++)
{
item.push_back(vect_x[x]);
}
// 循环vect_y是否存在
for (int x = 0; x < vect_y.size(); x++)
{
// 是否忽略重复元素
if (ignore == true)
{
// 判断item里面是否存在vect_y[x]元素
bool ref = find_vector_value(item, vect_y[x]);
if (ref != true)
{
item.push_back(vect_y[x]);
}
}
else
{
item.push_back(vect_y[x]);
}
}
return item;
}
int main(int argc,char * argv[])
{
std::vector<int> vect;
std::vector<int> x = { 1, 2, 3, 4, 5 };
std::vector<int> y = { 5, 6, 7, 8, 9, 10, 11};
// 合并两个列表元素,第三个参数判断,是否忽略重复元素合并
vect = extend_vector_list(x, y, true);
for (int x = 0; x < vect.size(); x++)
{
std::cout << "合并后: " << vect[x] << std::endl;
}
std::system("pause");
return 0;
}
11.14 字典与列表的嵌套
对于嵌套列表的实现,代码首先定义了一个vector
容器vect
,该容器中的每个元素都是另一个vector
容器。通过push_back()
函数,将两个内部vector
容器的元素添加到外部的vect
容器中。然后使用两层for
循环遍历外部和内部的容器,并输出它们所包含的每一个子元素。
对于嵌套多个字典的实现,代码定义了一个vector
容器vect
,该容器中的每个元素都是一个map
容器。map容器中的一个key
对应一个vector
容器。通过push_back()
函数,将两个内部map容器的元素添加到外部的vect容器中。然后使用两层for
循环遍历外部和内部的容器,并输出它们所包含的每一个子元素。
对于解析内部map
容器中的元素,需要使用迭代器进行遍历,具体实现还将其中的vector
容器解析出来,并输出其中的每一个元素。
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
// 实现列表中嵌套列表
// list[ ["192.168.1.1","root","1233"] , ["192.168.1.2","lyshark","123456"] ]
void list_nesting_list()
{
std::vector<std::vector<std::string>> vect;
std::vector<std::string> tmp;
tmp.push_back("192.168.1.1");
tmp.push_back("root");
tmp.push_back("1233");
vect.push_back(tmp);
tmp.clear();
tmp.push_back("192.168.1.2");
tmp.push_back("lyshark");
tmp.push_back("123456");
vect.push_back(tmp);
// 输出外层
for (int x = 0; x < vect.size(); x++)
{
// 输出内层
for (int y = 0; y < vect[x].size(); y++)
{
std::cout << vect[x][y] << std::endl;
}
}
}
// 实现列表中嵌套多个字典
// list[ {"Key": "192.168.1.1", "Value": [1,2,3,4,5] } , {"Key": "192.168.1.2", "Value" : [1,2,3] } ]
void list_nesting_dict()
{
std::vector< std::map<std::string, std::vector<int> > > vect;
// 填充map内部的vector容器
std::vector<int> internal;
std::string internal_string;
std::map<std::string, std::vector<int> > map;
// 插入第1条数据
internal_string = "192.168.1.1";
internal = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
map[internal_string] = internal;
vect.push_back(map);
// 插入后记得清理无用数据
internal.clear();
internal_string.clear();
map.clear();
// 插入第2条数据
internal_string = "192.168.1.2";
internal = { 1, 2, 3, 4, 5, 6 };
map[internal_string] = internal;
vect.push_back(map);
// 输出外层vector数据: std::vector<...> vect;
for (int x = 0; x < vect.size(); x++)
{
// 输出内层map数据: std::map<std::string, std::vector<int> >
std::map<std::string, std::vector<int>>::iterator iter;
for (iter = vect[x].begin(); iter != vect[x].end(); iter++)
{
std::cout << "Key: " << iter->first << std::endl;
// 解析并输出内部数据: std::vector<int>
std::vector<int> vector_ptr = iter->second;
for (int y = 0; y < vector_ptr.size(); y++)
{
std::cout << vector_ptr[y] << std::endl;
}
}
}
}
int main(int argc,char * argv[])
{
list_nesting_dict();
list_nesting_list();
std::system("pause");
return 0;
}
11.15 可存储多类型容器
这段代码使用了boost
库的variant
类型,实现了一个可变类型容器,用来存储两种不同类型,代码首先定义了一个名为var
的variant
类型数组,其大小为 3,可以容纳两种不同类型的vector
容器。同时,它将一个std::vectorstd::string
和std::vector<int>
赋值给var
数组的第0
个和第1
个元素。
随后,代码使用循环遍历该数组,通过boost
库的get
函数获取存储在var
数组中的元素。如果顺利获取到该元素,则可以进行类型判断,从中提取出对应的vector
容器。
最后,代码使用循环遍历表示vector
容器内部的元素,并输出每一个元素的值。
#include <iostream>
#include <string>
#include <vector>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
int main(int argc, char const *argv[])
{
// 定义可容纳 string,int 等类型的容器
boost::variant < std::vector<std::string>, std::vector<int>> var[3];
// 赋值第一个字符串数据集
std::vector<std::string> string_ptr;
string_ptr.push_back("string1");
string_ptr.push_back("strin2");
string_ptr.push_back("strin3");
var[0] = string_ptr;
// 赋值第二个字符串数据集
std::vector<int> int_ptr;
int_ptr.push_back(1);
int_ptr.push_back(2);
int_ptr.push_back(3);
var[1] = int_ptr;
for (int x = 0; x < 2; x++)
{
if (var[x].type() == typeid(std::vector<std::string>))
{
// 输出第一个字符串数据集
std::vector<std::string> string_vect;
string_vect = boost::get< std::vector<std::string> >(var[0]);
for (int x = 0; x < string_vect.size(); x++)
{
std::cout << "字符串结构: " << string_vect[x] << std::endl;
}
}
else if (var[x].type() == typeid(std::vector<int>))
{
// 输出第二个整数数据集
std::vector<int> int_vect;
int_vect = boost::get< std::vector<int> >(var[1]);
for (int x = 0; x < int_vect.size(); x++)
{
std::cout << "整数结构: " << int_vect[x] << std::endl;
}
}
}
std::system("pause");
return 0;
}
11.16 列表随机弹出元素
这段代码通过使用标准库和boost
库提供的随机数生成器方法,实现了从一个字符串vector
容器中随机弹出一个元素的功能。
函数get_random_value
使用标准库的srand()
函数配合std::rand()
函数实现随机生成整数。该随机生成器并不是真正的随机数生成器,而是伪随机数生成器。函数接受一个vector
容器,并返回其中随机抽取的一个元素。
函数get_boost_random_value
使用boost
库提供的mt19937
和uniform_int<>
类型的随机生成器实现真随机数的生成。该函数的实现相对更加健壮,并且需要的代码量也更多。此函数也接受一个vector
容器,并返回其中随机抽取的一个元素。
在main()
函数中,将标准库和boost
版本的随机函数各循环执行了10
次,并在每轮循环中输出从vector
容器中随机取出的元素。需要注意的是,在标准库实现弹出随机数的函数中,随机数生成器需要使用当前的系统时间作为种子,因此可产生结果不同的随机数序列。而在boost
实现的随机弹出元素的函数中,每次的随机数序列是非常随机且预测不可能的。
关于选择哪种生成随机数的方法,需根据实际情况进行选择。若仅是生成一些简单的随机数,则标准库的伪随机数生成器就足够使用;若需要生成复杂和预测性极低的应用程序,则需使用boost
库的真随机数生成器。
#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>
#include <time.h>
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
using namespace std;
using namespace boost;
// 标准库实现随机弹出元素
std::string get_random_value(std::vector<std::string> &ptr)
{
srand(unsigned(time(0)));
int count = ptr.size();
std::string ref = ptr.at(std::rand() % count);
return ref;
}
// boost实现的随机取出元素
std::string get_boost_random_value(std::vector<std::string> &ptr)
{
boost::mt19937 gen;
boost::uniform_int<>distribut(1, 10);
boost::variate_generator<mt19937 &, uniform_int<>> die(gen, distribut);
int count = ptr.size();
std::string ref = ptr.at(std::rand() % count);
return ref;
}
int main(int argc, char * argv[])
{
std::vector<std::string> vect;
vect.push_back("admin");
vect.push_back("lyshark");
vect.push_back("location");
vect.push_back("root");
// 标准库实现弹出随机数
for (int x = 0; x < 10; x++)
{
std::string ref = get_random_value(vect);
std::cout << "标准库随机元素: " << ref << std::endl;
}
// boost 实现弹出随机数
for (int x = 0; x < 10; x++)
{
std::string ref = get_boost_random_value(vect);
std::cout << "boost 随机元素: " << ref << std::endl;
}
std::system("pause");
return 0;
}
11.17 实现队列参数计算
这段代码定义了一个MyData
类,包括两个数据成员uuid
和uname
,以及一个get()
函数。该函数将传入的两个整数参数与uuid
进行加法计算,并返回计算结果。
在main()
函数中,定义了一个std::queue<MyData>
类型的队列对象queue_ptr
,插入了5
个MyData
类型的元素。接下来,在一个while
循环中,将队列顶部的元素取出,并根据MyData
对象的get()
函数计算它的数值加和。将计算结果与名字信息组成std::pair<std::string, int>
按顺序添加到一个vector
容器check_sum_list
中。
最后,循环遍历check_sum_list
向控制台输出每个std::pair<std::string, int>
元素的内容。
#include <iostream>
#include <string>
#include <vector>
#include <queue>
using namespace std;
class MyData
{
public:
int uuid;
std::string uname;
MyData(int x, std::string y)
{
uuid = x;
uname = y;
}
// 实现参数计算
int get(int value_a, int value_b)
{
return uuid + value_a + value_b;
}
};
int main(int argc, char *argv[])
{
std::vector<std::pair<std::string, int>> check_sum_list;
std::queue<MyData> queue_ptr;
// 插入数据
queue_ptr.push(MyData(1001, "admin"));
queue_ptr.push(MyData(1002, "lyshark"));
queue_ptr.push(MyData(1003, "root"));
queue_ptr.push(MyData(1004, "zhangsan"));
queue_ptr.push(MyData(1005, "wangwu"));
// 判断不为空
while (!queue_ptr.empty())
{
std::pair<std::string, int> temp;
// 取出队列头部元素
MyData ptr = queue_ptr.front();
int ref = ptr.get(100, 200);
// std::cout << "名字: " << ref << "计算后: " << ref << std::endl;
temp.first = ptr.uname;
temp.second = ref;
// 加入到vector容器
check_sum_list.push_back(temp);
queue_ptr.pop();
}
// 输出计算后的结果
for (int x = 0; x <= check_sum_list.size(); x++)
{
std::cout << check_sum_list[x].first << check_sum_list[x].second << std::endl;
}
std::system("pause");
return 0;
}
11.18 查找最大值/最小值
这段代码演示了如何使用Boost
库的minmax_element
算法,在一个vector
容器中找到最大值和最小值,并找到最小值对应的条目。
find_list() 函数演示了如何在一个整数容器中找到最大值和最小值,以及如何查找第一个最小值和最后一个最小值的下标。
find_dict_minmax_element() 函数演示了如何在一个std::pair<int, std::string>
容器中找到最小值和最大值,并返回最小值对应的std::pair<int, std::string>
条目。
需要时,可以在比较函数中指定自定义的元素排序方式。如果在重载的比较函数中返回的是 bool 值,那么此函数找到的是容器中的单个元素,而不是元素的下标。如果返回的是迭代器,那么这个函数找到的则是对应下标位置的元素。
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/minmax_element.hpp>
using namespace std;
// 寻找最大值与最小值
void find_list()
{
std::vector<int> vec = { 1, 4, 3, 2, 5, 6, 6, 6, 7, 8, 1, 4 };
auto x = boost::minmax_element(vec.begin(), vec.end());
cout << "最小值: " << *x.first << endl;
cout << "最大值: " << *x.second << endl;
decltype(vec.begin()) pos;
pos = boost::first_min_element(vec.begin(), vec.end());
cout << "第一个最小值: " << *pos << " 数组中位置: " << pos - vec.begin() << endl;
pos = boost::last_min_element(vec.begin(), vec.end());
cout << "最后一个最小值: " << *pos << " 数组中位置: " << pos - vec.begin() << endl;
}
// 寻找对组中的最大值与最小值,并返回对组
std::pair<int,std::string> find_dict_minmax_element(std::vector<std::pair<int,std::string>> ptr)
{
// 将数据集下标放入vect_ptr容器
std::vector<int> vect_ptr;
for (int x = 0; x < ptr.size(); x++)
{
vect_ptr.push_back(x);
}
// 寻找最最小值,返回的是下标号
auto x = boost::minmax_element(vect_ptr.begin(), vect_ptr.end());
// *x.second = 返回最小值 / *x.first = 返回最大值
std::pair<int, std::string> ref = ptr.at(*x.first);
return ref;
}
int main(int argc, char *argv[])
{
std::vector<std::pair<int, std::string>> ptr;
// 增加记录
ptr.push_back(std::pair < int, std::string >(98, "zhsngsan"));
ptr.push_back(std::pair < int, std::string >(65, "lisi"));
ptr.push_back(std::pair < int, std::string >(49, "wangwu"));
// 寻找最大最小值
std::pair<int, std::string> get = find_dict_minmax_element(ptr);
std::cout << "姓名: " << get.second << std::endl;
std::cout << "分数: " << get.first << std::endl;
std::system("pause");
return 0;
}
11.19 字典中嵌套结构体
这段代码演示了如何将自定义结构存储在map
容器中,并对这些结构进行迭代遍历和访问。MyStruct定义了一个自定义的结构类型,包括两个整数成员变量x
和y
,以及CheckSum()
函数,该函数计算x
和y
的和并返回结果。
在main
函数中,三个MyStruct
类型的结构对象struct_ptr_a、struct_ptr_b
和struct_ptr_c
分别设置了不同的x
和y
值,然后将它们插入到map
容器中,每个结构对象的唯一键值std::pair<int, MyStruct>(1, struct_ptr_a)
、std::pair<int, MyStruct>(2, struct_ptr_b)
和std::pair<int, MyStruct>(3, struct_ptr_c)
用于在map
容器中存储对应结构。
接下来使用for
循环迭代遍历结构体,并使用迭代器it
访问map
容器中的值。使用it->first
访问结构的键值,使用it->second.x
和it->second.y
访问结构的x
和y
成员变量,使用it->second.CheckSum()
访问结构的CheckSum()
函数的返回值。在控制台输出取出结构元素的值和计算结果。
#include <iostream>
#include <string>
#include <map>
using namespace std;
// 自定义结构
typedef struct
{
int x;
int y;
int CheckSum()
{
return x + y;
}
}MyStruct;
typedef std::map<int, MyStruct> struct_map;
int main(int argc, char* argv[])
{
struct_map map;
MyStruct struct_ptr_a, struct_ptr_b, struct_ptr_c;
struct_ptr_a.x = 100;
struct_ptr_a.y = 200;
struct_ptr_b.x = 10;
struct_ptr_b.y = 20;
struct_ptr_c.x = 12;
struct_ptr_c.y = 30;
// 将结构插入到map容器
map.insert(std::pair<int, MyStruct>(1, struct_ptr_a));
map.insert(std::pair<int, MyStruct>(2, struct_ptr_b));
map.insert(std::pair<int, MyStruct>(3, struct_ptr_c));
// 输出结构中的数据
for (struct_map::iterator it = map.begin(); it != map.end(); it++)
{
std::cout << "Key: " << it->first << " Value X: " << it->second.x << std::endl;
std::cout << "函数返回值: " << it->second.CheckSum() << std::endl;
}
std::system("pause");
return 0;
}
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!