当前位置: 首页 > news >正文

【C++之容器篇】map和set常见函数接口的使用与剖析

目录

    • 前言
    • 一、set
      • 1. 简介
      • 2. 成员类型
      • 3. 构造函数
        • (1) set()
        • (2)set(InputIterator first,InputIterator last)
        • (3)使用
      • 4. 拷贝构造函数和赋值运算符重载
      • 5. empty()
      • 6. size()
      • 7. insert()
        • (1)pair<iterator,bool> insert(const K& key)
        • (2)iterator insert(iterator pos,const K& key)
        • (3)void insert(InputIterator first,InputIterator last)
        • (4)综合测试set的插入接口
      • 8. erase()
        • (1)void erase(iterator pos)
        • (2)size_t erase(const K& key)
        • (3)void erase(iterator first,iterator last)
        • (4)综合测试set中的删除函数接口
      • 9.swap()
      • 10. clear()
      • 11. find()
      • 12.count()
      • 13. set<K>::iterator lower_bound(const K& key)
      • 14. set<int>::iterator upper_bound(const K& key)
    • 二、map
      • 1. 简介
      • 2. 成员类型
      • 3. 构造函数
      • 4. pair
      • 5. make_pair()
      • 5. 拷贝构造函数和赋值运算符重载函数
      • 6. empty()
      • 7. size()
      • 8. operator[]
      • 9. insert()
      • 10. erase()
        • (1) void erase(iterator pos)
        • (2) size_t erase(const K& key)
        • (3) void erase(iterator first,iterator last)
        • (4) 综合测试erase的所有接口
      • 11. swap()
      • 12. clear()
      • 13. find()
      • 14. count()
      • 15.lower_bound()
      • 16.upper_bound()

前言

map和set是数据结构中非常常用的结构,这两个结构都属于二叉搜索树,set中的结点存储的是关键字,map中的结点存储的是键值对。set和map都只支持存储唯一一个关键字,不允许关键字冗余,但是其衍生出来的multiset和multimap数据结构就支持存储多个关键子,下面将通过实际代码来详细介绍这两类数据结构的使用。

一、set

1. 简介

在这里插入图片描述

2. 成员类型

在这里插入图片描述

3. 构造函数

在这里插入图片描述

(1) set()

这个构造函数是一个无参的构造函数,是最常用的一个构造函数,其使用和之前学习的数据结构一样

(2)set(InputIterator first,InputIterator last)

这个构造函数是支持使用一段迭代器区间进行初始化,传迭代器区间的时候同样需要注意,传的必须是左闭右开的区间。

(3)使用

  • 代码:
void test_set1()
{// 使用set的构造函数//无参构造函数set<int> s1;set<string> s2;set<vector<int>> s3;// 使用一段迭代器区间进行构造string str("hello set(InputIterator first, InputIterator last)");vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);set<char> s4(str.begin(), str.end());set<int> s5(v.begin(), v.end());// 遍历setcout << "s1:" << endl;set<int>::iterator sit1 = s1.begin();while (sit1 != s1.end()){cout << *sit1 << " ";sit1++;}cout << endl;cout << "s2:" << endl;set<string>::iterator sit2 = s2.begin();while (sit2 != s2.end()){cout << *sit2 << " ";sit2++;}cout << endl;cout << "s4:" << endl;set<char>::iterator sit4 = s4.begin();while (sit4 != s4.end()){cout << *sit4 << " ";sit4++;}cout << endl;cout << "s5:" << endl;set<int>::iterator sit5 = s5.begin();while (sit5 != s5.end()){cout << *sit5 << " ";sit5++;}cout << endl;}

运行结果:
在这里插入图片描述

4. 拷贝构造函数和赋值运算符重载

在这里插入图片描述
在这里插入图片描述

  • 代码:
void test_set2()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);set<int> s1(v.begin(), v.end());set<int> s2 = s1;// 调用拷贝构造函数set<int> s3;s3 = s2;// 调用赋值运算符重载函数cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;cout << "s2:" << endl;for (auto& e : s2){cout << e << " ";}cout << endl;cout << "s3:" << endl;for (auto& e : s3){cout << e << " ";}cout << endl;}

运行结果:
在这里插入图片描述

5. empty()

这个函数的功能就是判断set是否为空,如果为空,则返回true,否则返回false
在这里插入图片描述

6. size()

这个函数是求set中结点的个数的
在这里插入图片描述

  • 代码:
void test_set3()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);set<int> s1(v.begin(), v.end());cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;cout << "s1中的结点个数为:" << s1.size() << endl;
}

运行结果:
在这里插入图片描述

7. insert()

在这里插入图片描述

(1)pair<iterator,bool> insert(const K& key)

这个函数支持向set中插入一个key,插入之后会返回一个键值对,键值对其实本质就是一个结构体,其中存储两个值,分别叫做first和second,其中的first是iterator,也就是指向插入结点的迭代器,second是bool,标识插入是否成功,当插入的key在set中是存在的,则插入失败,返回的键值对中的迭代器指向这个已经存在的值,键值对中的bool值为false,如果插入的key不存在,则返回的键值对中的迭代器指向新插入的结点,bool值为true。

(2)iterator insert(iterator pos,const K& key)

这个函数支持在pos位置处插入一个key,返回插入位置的迭代器,这个接口平时很少用,也不太能用,因为值不能随便向set中进行插入,很容易会破坏set的结构。

(3)void insert(InputIterator first,InputIterator last)

这个函数支持向set中插入一段迭代器区间,没有返回值

(4)综合测试set的插入接口

  • 代码:
void test_set4()
{// 测试set的插入函数set<int> s;pair<set<int>::iterator,bool> p1 = s.insert(1);cout << *(p1.first) << endl;pair<set<int>::iterator, bool> p2 = s.insert(3);cout << *(p2.first) << endl;pair<set<int>::iterator, bool> p3 = s.insert(2);cout << *(p3.first) << endl;pair<set<int>::iterator, bool> p4 = s.insert(6);cout << *(p4.first) << endl;pair<set<int>::iterator, bool> p5 = s.insert(4);cout << *(p5.first) << endl;pair<set<int>::iterator, bool> p6 = s.insert(8);cout << *(p6.first) << endl;for (auto& e : s){cout << e << " ";}cout << endl;// 在3位置处插入30set<int>::iterator pos = s.find(3);if (pos != s.end()){// 找到了set<int>::iterator pos1 = s.insert(pos, 30);cout << *pos1 << endl;}else{// 找不到cout << "没有找到此值" << endl;}// 构造一个vectorvector<int> v = { 10,7,5,40,50 };// 向s 插入一段迭代器区间s.insert(v.begin(), v.end());for (auto& e : s){cout << e << " ";}cout << endl;}

运行结果:
在这里插入图片描述

8. erase()

在这里插入图片描述

(1)void erase(iterator pos)

这个接口支持删除某个位置的值,需要提供删除值的位置(迭代器)

(2)size_t erase(const K& key)

这个接口支持删除set中的某一个值为key的结点,需要提供删除的key

(3)void erase(iterator first,iterator last)

这个接口支持删除set中的某一段连续的值

(4)综合测试set中的删除函数接口

  • 代码
void test_set5()
{//测试set中的删除函数set<int> s;s.insert(10);s.insert(4);s.insert(6);s.insert(2);s.insert(8);s.insert(5);s.insert(1);for (auto& e : s){cout << e << " ";}cout << endl;// 删除某一个位置的迭代器// 先通过find去获取这个值的迭代器set<int>::iterator pos = s.find(4);if (pos != s.end()){// 找到了s.erase(pos);}for (auto& e : s){cout << e << " ";}cout << endl;// 删除某一个值s.erase(10);for (auto& e : s){cout << e << " ";}cout << endl;// 删除某一段区间s.erase(s.begin(), s.end());for (auto& e : s){cout << e << " ";}cout << endl;}

运行结果:
在这里插入图片描述

9.swap()

这个函数支持交换两个set对象的内容
在这里插入图片描述

  • 代码:
void test_set6()
{// 测试交换函数set<int> s1;s1.insert(1);s1.insert(6);s1.insert(5);s1.insert(4);s1.insert(3);s1.insert(2);cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;set<int> s2;s2.insert(10);s2.insert(9);s2.insert(8);s2.insert(7);s2.insert(6);s2.insert(15);cout << "s2:" << endl;for (auto& e : s2){cout << e << " ";}cout << endl;s1.swap(s2);cout << "swap s1 and s2:" << endl;cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;cout << "s2:" << endl;for (auto& e : s2){cout << e << " ";}cout << endl;
}

运行结果:
在这里插入图片描述

10. clear()

在这里插入图片描述
这个函数的功能是将set中的所有结点删除

void test_set7()
{// 测试交换函数set<int> s1;s1.insert(1);s1.insert(6);s1.insert(5);s1.insert(4);s1.insert(3);s1.insert(2);cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;s1.clear();cout << "s1:" << endl;for (auto& e : s1){cout << e << " ";}cout << endl;
}

运行结果:
在这里插入图片描述

11. find()

在这里插入图片描述
这个函数是支持在set中查找一个值,如果找到,则返回这个结点的迭代器,否则返回end()。这个find接口需要和算法中的find进行区分,set中的find函数是根据搜索树的性质进行查找的,而算法中的find是进行暴力查找的,所以这两者的查找效率是不一样的。

void test_set8()
{//测试set中的findvector<int> v = { 3,4,7,5,1,9,8 };set<int> s(v.begin(),v.end());set<int>::iterator pos;for (auto& e : v){pos = s.find(e);if (pos != s.end()){// 找到了cout << *pos << endl;}else{// 找不到cout << "找不到此值" << endl;}}
}

运行结果:
在这里插入图片描述

12.count()

在这里插入图片描述

这个函数的作用是求set中对应结点的个数,理论上set中的每一个结点在set中只能出现,所以查找的值返回的值次数理论上只能是1或者0。所以在set中,count()函数也能充当查找的功能。

void test_set9()
{//测试set中的findvector<int> v = { 3,4,7,5,1,9,8 };set<int> s(v.begin(), v.end());set<int>::iterator pos;for (auto& e : v){cout << s.count(e) << " ";}cout << endl;vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };for (auto& e: v1){cout << e << "出现的次数:" << s.count(e) << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

13. set::iterator lower_bound(const K& key)

在这里插入图片描述
这个函数的功能是返回比key大或者相等的结点的迭代器

void test_set10()
{// 测试lower_boundvector<int> v = { 3,4,7,5,1,9,8 };set<int> s(v.begin(), v.end());// 找的值在set中存在set<int>::iterator lowIt = s.lower_bound(4);if (lowIt != s.end()){cout << *lowIt << endl;}else{cout << "找不到" << endl;}// 找的值在set中不存在lowIt = s.lower_bound(6);if (lowIt != s.end()){cout << *lowIt << endl;}else{cout << "找不到" << endl;}
}

运行结果:
在这里插入图片描述

14. set::iterator upper_bound(const K& key)

在这里插入图片描述
这个函数的功能是返回比key大的结点的迭代器(不包含key的结点)

void test_set11()
{// 测试upper_boundvector<int> v = { 3,4,7,5,1,9,8 };set<int> s(v.begin(), v.end());// 找的值在set中存在set<int>::iterator lowIt = s.upper_bound(4);if (lowIt != s.end()){cout << *lowIt << endl;}else{cout << "找不到" << endl;}// 找的值在set中不存在lowIt = s.upper_bound(6);if (lowIt != s.end()){cout << *lowIt << endl;}else{cout << "找不到" << endl;}
}

运行结果:
在这里插入图片描述

  • lowerbound()和upper_bound()的综合使用场景
    可以和set.erase(InputIterator first,InputIterator last)这个函数接口进行使用,删除一段迭代器区间
    代码:
void test_set12()
{// 综合测试lower_bound()和upper_bound()的使用vector<int> v = { 2,3,5,1,7,6,4,9,8,10 };set<int> s(v.begin(), v.end());for (auto& e : s){cout << e << " ";}cout << endl;//删除1-6的值set<int>::iterator lowIt = s.lower_bound(1);set<int>::iterator upIt = s.upper_bound(6);s.erase(lowIt, upIt);for (auto& e : s){cout << e << " ";}cout << endl;
}

运行结果:
在这里插入图片描述

二、map

1. 简介

在这里插入图片描述

2. 成员类型

在这里插入图片描述

3. 构造函数

在这里插入图片描述
这个构造函数中比较常用的是使用无参构造函数进行创建对象


void test_map1()
{// 无参构造函数map<int, int> m1;map<string, string> m2;map<string, int> m3;map<vector<int>, vector<int>> m4;
}

4. pair

pair是键值对的意思,其本质是一个结构体,其中包含两个成员变量firstsecond,使用pair的时候需要注意包头文件
在这里插入图片描述

// pair
template <class K,class V>
struct pair
{K first;V second;
};

5. make_pair()

在这里插入图片描述
make_pair本质上是一个函数调用,就算将两个类型的值传给make_pair()然后构造出一个pair类型出来
其中需要注意,我们在传pair类型的参数的时候,是需要指明模板参数的,但是使用make_pair的时候是不需要指明模板参数的,后面的场景将会遇到

5. 拷贝构造函数和赋值运算符重载函数

使用方法和之前学习的数据结构一模一样。

void test_map14()
{// 使用拷贝构造函数和赋值运算符重载函数map<int, int> m;m[1] = 1;m[2] = 2;m[3] = 3;m[4] = 4;m[5] = 5;m[6] = 6;m[7] = 7;map<int, int> m1 = m;// 调用拷贝构造函数map<int, int> m2;m2 = m1;// 调用赋值运算符重载函数cout << "m:" << endl;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;cout << "m1:" << endl;for (auto& e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;cout << "m2:" << endl;for (auto& e : m2){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

6. empty()

在这里插入图片描述
判断map是否为空,如果为空,返回true,否则,返回false

void test_map10()
{//测试empty()map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(2, 1));m.insert(make_pair(3, 1));m.insert(make_pair(4, 1));m.insert(make_pair(5, 1));m.insert(make_pair(6, 1));m.insert(make_pair(7, 1));m.insert(make_pair(8, 1));m.insert(make_pair(9, 1));if (m.empty()){cout << "该树为空" << endl;}else{cout << "该树不为空" << endl;}m.clear();if (m.empty()){cout << "该树为空" << endl;}else{cout << "该树不为空" << endl;}}

运行结果:
在这里插入图片描述

7. size()

返回map中结点的个数
在这里插入图片描述

void test_map11()
{// 测试size()map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(2, 1));m.insert(make_pair(3, 1));m.insert(make_pair(4, 1));m.insert(make_pair(5, 1));m.insert(make_pair(6, 1));m.insert(make_pair(7, 1));m.insert(make_pair(8, 1));m.insert(make_pair(9, 1));cout << "该树的结点为" << m.size() << endl;m.clear();cout << "该树的结点为" << m.size() << endl;}

运行结果:
在这里插入图片描述

8. operator[]

在这里插入图片描述
这个函数需要中单关注其返回值,其返回值是一个mapped_type&类型,也就是value的引用,所以返回值是支持修改的,其中涉及的插入过程中的细节在insert()中会进行细讲。
综上,我们可以知道,operator[]()充当的作用可以是插入,也可以是修改,也可以是仅仅访问某一个结点中的值

  • 代码1:插入+访问
void test_map12()
{// 测试[]map<int, int> m;m[1] = 1;m[2] = 2;m[3] = 3;m[4] = 4;m[5] = 5;m[6] = 6;m[7] = 7;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;}

运行结果:
在这里插入图片描述

  • 代码2:插入+访问+修改
void test_map13()
{// 测试[]map<int, int> m;m[1] = 1;m[2] = 2;m[3] = 3;m[4] = 4;m[5] = 5;m[6] = 6;m[7] = 7;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;m[1] = 11;m[2] = 22;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

9. insert()

在这里插入图片描述
上面的接口中最常用的是插入pair类型的,这个函数需要中单关注其返回值,其返回值是一个pair<iterator,bool>类型,operator[]() 函数首先会调用 insert()函数,如果插入的值存在,则返回的pair<iterator,bool>中的iterator指向的是这个存在的结点,bool为false,表示此次插入失败,如果插入的值不存在,则成功插入,返回的pair<iterator,bool>中的iterator指向这个新插入的迭代器,bool为true,表示此次插入是成功的。
综上,我们可以知道,operator[]()充当的作用可以是插入,也可以是修改,也可以是仅仅访问某一个结点中的值使用如下:

void test_map2()
{// std::pair<iterator,bool> set::insert(make_pair(key,value));map<string, string> m1;m1.insert(std::pair<string, string>("string", "字符串"));m1.insert(make_pair("sort", "排序"));m1.insert(make_pair("left", "左边"));for (auto& e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

10. erase()

在这里插入图片描述

(1) void erase(iterator pos)

这个接口是支持给定迭代器,删除迭代器位置处的结点

(2) size_t erase(const K& key)

这个接口是支持删除给定的key的结点

(3) void erase(iterator first,iterator last)

这个接口支持删除一段迭代器区间,一般可以和lower_bound()和upper_bound()进行使用

(4) 综合测试erase的所有接口

  • 代码:
void test_map3()
{map<string, string> m;m.insert(make_pair("string", "字符串"));m.insert(make_pair("left", "左边"));m.insert(make_pair("apple", "苹果"));m.insert(make_pair("insert", "插入"));m.insert(make_pair("erase", "删除"));for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;// 删除erase:支持通过key进行删除m.erase("erase");for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;// 删除insert:通过iterator 进行删除// 找到insert的迭代器map<string, string>::iterator pos = m.find("insert");if (pos != m.end()){// 找到了m.erase(pos);}else{// 找不到cout << "找不到" << endl;}for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;// 删除全部的结点:使用迭代器区间进行删除m.erase(m.begin(), m.end());for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;}

运行结果:
在这里插入图片描述

11. swap()

在这里插入图片描述
这个交换函数的底层是交换两个map中的根节点指针,std中的交换函数实现的是深拷贝,这个要区分开来。

void test_map4()
{// 测试交换函数map<string, string> m;m.insert(make_pair("string", "字符串"));m.insert(make_pair("left", "左边"));m.insert(make_pair("apple", "苹果"));m.insert(make_pair("insert", "插入"));m.insert(make_pair("erase", "删除"));map<string, string> m1;m1.insert(std::pair<string, string>("string", "字符串"));m1.insert(make_pair("sort", "排序"));m1.insert(make_pair("left", "左边"));cout << "m:" << endl;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;cout << "m1:" << endl;for (auto& e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;m1.swap(m);cout << "m:" << endl;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;cout << "m1:" << endl;for (auto& e : m1){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

12. clear()

在这里插入图片描述
这个函数的功能是完成map中结点资源的清理

void test_map5()
{// 测试clearmap<string, string> m;m.insert(make_pair("string", "字符串"));m.insert(make_pair("left", "左边"));m.insert(make_pair("apple", "苹果"));m.insert(make_pair("insert", "插入"));m.insert(make_pair("erase", "删除"));for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;m.clear();for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

13. find()

在这里插入图片描述
这个函数的功能是通过key去找迭代器,所以find函数返回的是找的结点的迭代器,如果找到,返回找的结点的迭代器,否则,返回end()

void test_map6()
{map<string, string> m;m.insert(make_pair("string", "字符串"));m.insert(make_pair("left", "左边"));m.insert(make_pair("apple", "苹果"));m.insert(make_pair("insert", "插入"));m.insert(make_pair("erase", "删除"));for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;map<string, string>::iterator pos = m.find("apple");if (pos != m.end()){// 找到了cout << pos->first << ":" << pos->second << endl;}else{// 找不到cout << "找不到" << endl;}
}

运行结果:
在这里插入图片描述

14. count()

计算map中结点出现的个数,理论上对于map,因为map中的数据不能出现冗余,所以map中count的返回值只可能是0或者1

15.lower_bound()

在这里插入图片描述
通过key,调用lower_bound()函数返回大于等于key的结点的迭代器

void test_map7()
{// 测试lower_bound()map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(2, 1));m.insert(make_pair(3, 1));m.insert(make_pair(4, 1));m.insert(make_pair(5, 1));m.insert(make_pair(6, 1));// map中存在的值map<int, int>::iterator lowIt = m.lower_bound(2);if (lowIt != m.end()){// 找到了cout << lowIt->first << ":" << lowIt->second << endl;}else{// 找不到cout << "找不到" << endl;}// map中不存在的值lowIt = m.lower_bound(0);if (lowIt != m.end()){// 找到了cout << lowIt->first << ":" << lowIt->second << endl;}else{// 找不到cout << "找不到" << endl;}}

运行结果:
在这里插入图片描述

16.upper_bound()

在这里插入图片描述
通过key,调用lower_bound()函数返回大于key的结点的迭代器

void test_map8()
{// 测试upper_bound()map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(2, 1));m.insert(make_pair(3, 1));m.insert(make_pair(4, 1));m.insert(make_pair(5, 1));m.insert(make_pair(6, 1));// map中存在的值map<int, int>::iterator upIt = m.upper_bound(2);if (upIt != m.end()){// 找到了cout << upIt->first << ":" << upIt->second << endl;}else{// 找不到cout << "找不到" << endl;}// map中不存在的值upIt = m.upper_bound(0);if (upIt != m.end()){// 找到了cout << upIt->first << ":" << upIt->second << endl;}else{// 找不到cout << "找不到" << endl;}}

运行结果:
在这里插入图片描述

  • 综合使用lower_bound()和upper_bound()
void test_map9()
{map<int, int> m;m.insert(make_pair(1, 1));m.insert(make_pair(2, 1));m.insert(make_pair(3, 1));m.insert(make_pair(4, 1));m.insert(make_pair(5, 1));m.insert(make_pair(6, 1));m.insert(make_pair(7, 1));m.insert(make_pair(8, 1));m.insert(make_pair(9, 1));// 删除前遍历一次for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;// 要求删除1-4的值map<int, int>::iterator lowIt = m.lower_bound(1);map<int, int>::iterator upIt = m.upper_bound(4);// 调用erase()m.erase(lowIt, upIt);// 删除后遍历一次for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;
}

运行结果:
在这里插入图片描述

相关文章:

【C++之容器篇】map和set常见函数接口的使用与剖析

目录前言一、set1. 简介2. 成员类型3. 构造函数(1) set()(2)set(InputIterator first,InputIterator last)(3)使用4. 拷贝构造函数和赋值运算符重载5. empty()6. size()7. insert()(1)pair<iterator,bool> insert(const K& key)(2)iterator insert(iterator pos,cons…...

虚拟DOM是什么

参考文章做的总结&#xff0c;如有不足之处请指正&#xff01; 在讲虚拟dom之前&#xff0c;先讲讲&#xff0c;为什么前端操作dom会导致页面性能降低&#xff1f; 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎&#xff1f; JavaScript引擎是一个专门处理JavaScript脚…...

进程通信方式

无名管道( pipe )&#xff1a; 管道是一种半双工的通信方式&#xff0c;数据只能单向流动&#xff0c;而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。高级管道&#xff08;popen&#xff09;&#xff1a; 将另一个程序当做一个新的进程在当前程序进…...

强化学习基础知识

强化学习是一种机器学习方法&#xff0c;通过agent与environment的互动&#xff0c;学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识&#xff0c;与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…...

LeetCode230218_148、654. 最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…...

WordPress 是什么?.com 和 .org 的 WordPress 有什么差异?

本篇文章会介绍这次WordPress 5.8核心版本所带来的其中一项新功能&#xff1a;内存块小工具&#xff08;Widget&#xff09;此次更新把小工具编辑设定的页面也改成用「内存块编辑」的概念&#xff0c;就跟内置的「古腾堡」编辑器一样&#xff0c;把所有元件都内存块化&#xff…...

java8新特性【2023】

Lambda表达式 新的一套语法规则 是一个匿名函数 Testpublic void test1(){Runnable r1 new Runnable(){Overridepublic void run() {System.out.println("线程A");}};r1.run();System.out.println("");Runnable r2 () -> System.out.println("…...

刷题记录:牛客NC51101Lost Cows

传送门:牛客 题目描述: (2≤N≤8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood watering hole and drank a few too many beers before dinner. When it was time to line up for their ev…...

华为OD机试 - 不等式 | 备考思路,刷题要点,答疑 【新解法】

最近更新的博客 华为OD机试 - 寻找路径 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最小叶子节点 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 对称美学 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】华…...

GuLi商城-SpringCloud-OpenFeign测试远程调用

1. Feign 简介 Feign 是一个声明式的 HTTP 客户端&#xff0c;它的目的就是让远程调用更加简单。Feign 提供了HTTP请 求的模板&#xff0c;通过编写简单的接口和插入注解&#xff0c;就可以定义好 HTTP 请求的参数、格式、地址等信 息。Feign 整合了 Ribbon&#xff08;负载…...

阿里云_山东鼎信短信的使用(云市场)

目录山东鼎信API工具类随机验证码工具类进行测试Pom依赖(可以先导入依赖)创建controllerSmsServiceSmsServiceImplswagger测试(也可以使用postman)山东鼎信API工具类 山东鼎信短信官网 找到java的Api&#xff0c;复制下来 适当改了一下&#xff0c;为了调用(类名SmsUtils) p…...

基于虚拟机机的代码保护技术

虚拟机保护技术是基于x86汇编系统的可执行代码转换为字节码指令系统的代码&#xff0c;以达到保护原有指令不被轻易逆向和篡改的目的。 字节码&#xff08;Byte-code&#xff09;是一种包含执行程序&#xff0c;由一序列 op 代码/数据对组成的 &#xff0c;是一种中间码。字节是…...

Win10耳机有声音麦不能说话怎么办?麦克风说话别人听不到解决方法

网上找了一些解决办法&#xff0c;一般都是重复的&#xff0c;几个设置调来调去也就那样&#xff0c;没什么用 这种问题一般是“老式”一点的台式机会出现&#xff0c;提供的解决办法如下&#xff1a; 首先下载带面板的音频管理器&#xff0c;如realtek高清晰音频管理器&…...

The 22nd Japanese Olympiad in Informatics (JOI 2022/2023) Final Round 题解

交题&#xff1a;https://cms.ioi-jp.org/documentation A 给一个序列 a1,⋯,ana_1,\cdots,a_na1​,⋯,an​。 执行nnn个操作&#xff0c;第iii个操作为找出第iii个数前离其最近且与它相同的数的位置&#xff0c;把这两个数之间的数全部赋值aia_iai​。求最后的序列。 考虑第…...

openEuler RISC-V 成功适配 VisionFive 2 单板计算机

近日&#xff0c;RISC-V SIG 成功在 VisionFive 2 开发板上适配欧拉操作系统&#xff0c;目前最新版本的 openEuler RISC-V 22.03 V2 镜像已在 VisionFive 2 开发板上可用&#xff0c;这是 openEuler 推动 RISC-V 生态演进的又一新进展。下载链接​​https://mirror.iscas.ac.c…...

2005-2022中国企业对外直接投资、OFDI海外投资明细、中国全球投资追踪数据CGIT(含非建筑施工类问题投资)

中国全球投资跟踪”&#xff08;China Global Investment Tracker&#xff09;&#xff0c;数据库&#xff0c;美国企业研究所于1月28日发布。数据库显示&#xff0c;2005年以来&#xff0c;中国对外投资和建设总额已接近2万亿美元。该数据库是唯一一套涵盖中国全球投资和建设的…...

PCB学习笔记——使用嘉立创在线绘制原理图与PCB

嘉立创软件地址&#xff1a;https://lceda.cn/ 新建工程-新建原理图&#xff0c;在元件库中可以搜索元器件&#xff0c;可以直接放置在原理图上。 原理图绘制完成后&#xff0c;保存文件&#xff0c;设计-原理图转PCB&#xff0c;可以直接生成对应的PCB&#xff0c;设置边框&…...

【C++】类型转化

&#x1f308;欢迎来到C专栏~~类型转化 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&…...

Mybatis -- resultMap以及分页

查询为null问题 要解决的问题&#xff1a;属性名和字段名不一致 环境&#xff1a;新建一个项目&#xff0c;将之前的项目拷贝过来 1、查看数据库的字段名 2、Java中的实体类设计 public class User { private int id; //id private String name; //姓名 private String passwo…...

Linux之进程

一.冯诺依曼体系 在计算机中&#xff0c;CPU&#xff08;中央处理器&#xff09;是不直接跟外部设备直接进行通信的&#xff0c;因为CPU处理速度太快了&#xff0c;而设备的数据读取和输入有太慢&#xff0c;而是CPU以及外设直接跟存储器&#xff08;内存&#xff09;打交道&am…...

结构体——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是结构体噢&#xff0c;之前我们在初始C语言中其实就已经学习过了结构体的知识&#xff0c;但是不是很全面&#xff0c;这次&#xff0c;我们也只是稍微详细一点&#xff0c;敬请期待小雅兰之后的博客&#xff…...

CCNP350-401学习笔记(51-100题)

51、Which statement about a fabric access point is true?A. It is in local mode and must be connected directly to the fabric edge switch. B. It is in local mode and must be connected directly to the fabric border node C. It is in FlexConnect mode and must …...

C语言学习_DAY_4_判断语句if_else和分支语句switch_case【C语言学习笔记】

高质量博主&#xff0c;点个关注不迷路&#x1f338;&#x1f338;&#x1f338;&#xff01; 目录 1.案例引入 2.if判断语句的语法与注意事项 3.switch多分支语句的语法与注意事项 前言: 书接上回&#xff0c;我们已经学习了所有的数据类型、运算符&#xff0c;并且可以书写…...

实验07 赫夫曼编码及综合2022(带程序填空)

A. 【程序填空】赫夫曼编码题目描述给定n个叶子的权值&#xff0c;根据这些权值构造huffman树&#xff0c;并输出huffman编码参考课本第6.6节的算法6.12&#xff0c;注意算法中数组访问是从位置1开始赫夫曼构建中&#xff0c;默认左孩子权值不大于右孩子权值如果遇到两个孩子权…...

分布式 CAP BASE理论

文章目录CAP简介不是所谓的“3 选 2”CAP 实际应用案例BASE简介BASE 理论的核心思想总结CAP 简介 在理论计算机科学中&#xff0c;CAP 定理&#xff08;CAP theorem&#xff09;指出对于一个分布式系统来说&#xff0c;当设计读写操作时&#xff0c;只能同时满足以下三点中的…...

三调地类筛选器,Arcgis地类筛选

三调地类在使用是&#xff0c;需要分类统计&#xff0c;这个可以用于筛选&#xff1b; 标准地类筛选 农用地&#xff1a; DLBM IN(0303,0304,0306,0402,0101,0102,0103,0201,0201K,0202,0202K,0203,0203K,0204,0204K,0301,0301K,0302,0302K,0305,0307,0307K,0401,0403,0403K…...

华为OD机试 - 密室逃生游戏(Python)

密室逃生游戏 题目 小强增在参加《密室逃生》游戏,当前关卡要求找到符合给定 密码 K(升序的不重复小写字母组成) 的箱子, 并给出箱子编号,箱子编号为 1~N 。 每个箱子中都有一个 字符串 s ,字符串由大写字母、小写字母、数字、标点符号、空格组成, 需要在这些字符串中…...

白话C#之委托

一、什么是委托&#xff1f; 书本上是这样来定义委托的&#xff1a; 委托是一种动态调用方法的类型&#xff0c;属于引用型。委托是对方法的抽象和封装。委托对象实质上代表了方法的引用&#xff08;即内存地址&#xff09;。委托通常是委托某个方法来实现具体的功能。当我们调…...

jsp高校教职工管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 高校教职工管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助mvc模式 serlvetdaobean方式开发&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#…...

2023年数学建模美赛A题(A drought stricken plant communities)分析与编程

2023年数学建模美赛A题&#xff08;A drought stricken plant communities&#xff09;分析与编程 2023年数学建模美赛D题&#xff08;Prioritizing the UN Sustainability Goals&#xff09;分析与编程 特别提示&#xff1a; 1 本文介绍2023年美赛题目&#xff0c;进行深入分析…...

个人网站托管/百度下载安装app

在我们先前的文章&#xff02;如何在Ubuntu手机中使用前置照相机&#xff02;对如何使用前置照相机给出了一个解决方案&#xff0e;事实上&#xff0c;在我们最新的Camera API中 (QtMultiMedia 5.6)&#xff0c;已经有新的API来完成这个功能了&#xff0e;我们不再需要额外的C代…...

建设银行招标网站/深圳网络推广专员

返回目录 今天写缓存篇的第一篇文章&#xff0c;在写完目录后&#xff0c;得到了一些朋友的关注&#xff0c;这给我之后的写作带来了无穷的力量&#xff0c;在这里&#xff0c;感谢那几位伙伴&#xff0c;哈哈&#xff01; 书归正传&#xff0c;今天我带来一个Static静态成员的…...

教育培训的网站建设/软文是什么

作为一个从事.NET Web技术的开发人员&#xff0c;似乎没有什么理由可以不懂微软自己的AJAX框架&#xff0c;虽然它可能不太好用&#xff0c;或者用起来没有像jQuery这样的框架那么爽。我没有怎么用过UpdatePanel来做过复杂的东西&#xff0c;所以对于这个的优缺点就不予置评了。…...

网站的建设原始代码/重庆网站建设外包

一、 ng-class ng-class 指令用于给 HTML 元素动态绑定一个或多个 CSS 类。 ng-class 指令的值可以是字符串&#xff0c;对象&#xff0c;或一个数组。 如果是字符串&#xff0c;多个类名使用空格分隔。如果是对象&#xff0c;需要使用 key-value 对&#xff0c;key 为你想要添…...

怎样免费建一个网站/怎么建公司网站

储蓄这个词&#xff0c;在中国人来看&#xff0c;已经很是熟悉了。 中国人爱储蓄&#xff0c;全球皆知&#xff01; 我们从开始工作挣钱后&#xff0c;父母就安排我们&#xff1a;“钱不要乱花&#xff0c;能存就先存起来。” 但回头看一下自己的支付宝账单&#xff0c;我们…...

太原网站建设世纪优创/最好的网络营销软件

来都来了,怎么说也你也踩下我的说说是吧,求回复...