【C++】set与map的使用

news/2024/9/22 18:37:24/

目录

一、set:

1、set介绍:

2、常用构造:

3、常用修改操作:

(1)insert:

(2)find

(3)erase:

4、其他操作:

(1)count:

(2)lower_bound、upper_bound:

multiset:

二、map:

1、map介绍:

2、常用构造:

3、常用修改操作:

(1)insert、emplace:

(2)find:

(3)erase:

4、其他操作:

(1)count:

(2)lower_bound、upper_bound:

multimap:


一、set:

1、set介绍:

        set是按照一定次序存储元素的容器,它用于存储唯一的元素(即在容器中没有重复的元素)通常用于需要快速查找、插入和删除元素的场景,底层通常是用红黑树来实现这些操作的快速性。

特点:

  1. 在set中的元素都具有唯一性,也就是set会自动排序+去重,默认按照升序排序。
  2. 往set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. 可以使用set的迭代器遍历set中的元素,即可得到升序的有序序列。
  4. set的查找效率是非常高效的:O(logN),底层由红黑树实现(高度次查找)。

2、常用构造:

void Test1()
{vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };set<int> s1(v.begin(), v.end()); // 区间构造set<int> s2(s1); // 拷贝构造set<int> s3;  s3 = s2; // 赋值重载// 遍历可得升序的去重序列for (auto e : s1){cout << e << " ";}cout << endl;
}

3、常用修改操作:

(1)insert:

set的插入操作就只用insert就可以了,因为无论从哪个位置插入,最终都会被排序好。至于去重的功能,就是在树中(set的底层就是红黑树)如果已存在要插入的值,则取消插入操作。

void Test2()
{set<int> s;s.insert(6);s.insert(3);s.insert(8);s.insert(7);s.insert(6);s.insert(9);s.insert(0);s.insert(3);s.insert(7);s.insert(5);for (auto e : s){cout << e << " ";}cout << endl;
}

(2)find

find查找找到了返回指定值位置的迭代器,找不到返回end();

void Test4()
{vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };set<int> s(v.begin(), v.end());auto it = s.find(3);cout << *it << endl; // 输出3auto it2 = s.find(20);if (it2 == s.end()) cout << "it2 == s.end()" << endl;}

(3)erase:

erase 的三种删除:

指定位置删除:s.erase(iterator)

指定区间删除:s.erase(first,second) 

指定值删除:s.erase(val);

void Test3()
{vector<int> v = { 4,5,8,3,2,5,6,9,4,3 };set<int> s(v.begin(), v.end());cout << "s:";for (auto e : s){cout << e << " ";}cout << endl << endl;// s.erase(iterator)cout << "s.erase(iterator): erase(begin()): ";s.erase(s.begin());for (auto e : s){cout << e << " ";}cout << endl << endl;// s.erase(val)cout << "s.erase(val): val = 6: ";s.erase(6);for (auto e : s){cout << e << " ";}cout << endl << endl;// s.erase(first, second),cout << "s.erase(first,second): erase(s.begin(),s.end()) : ";s.erase(s.begin(),s.end());for (auto e : s){cout << e << " ";}cout << endl; cout << "因为区间删除全删了,所以set中没有元素";
}

4、其他操作:

(1)count:

count(val) 的操作就是在容器中查找是否有值val,如果有返回1,没有返回0。

(2)lower_bound、upper_bound:

lower_bound(key_value)返回第一个大于等于key_value的定位器

upper_bound(key_value)返回第一个大于key_value的定位器

失败都返回end( );    可以理解为两者分别是一个开、闭区间【   )

void Test6()
{vector<int> v = { 1,2,3,4,5,6,7,8,9,10,11,12 };set<int> s(v.begin(), v.end());cout << "s: ";for (auto e : s){cout << e << " ";}cout << endl << endl;// 可以配合erase实现区间删除的功能s.erase(s.lower_bound(3), s.upper_bound(9));cout << "删除区间3 ~ 9:  ";for (auto e : s){cout << e << " ";}cout << endl;
}

multiset:

        前面说到set会自动去重,但是如果不想让其去重的话可以使用multiset,从用法上来讲和set差别不大,但是不会去重,在插入时可以默认相同值往右插入,但是也可能会旋转到左分支去,在查找并返回时,为了配合删除但不影响整棵树的原则,默认是找中序遍历的第一个值,也就是说找到该值后你还不能停,还要去你的左子树看看还有没有相同值,因为中序遍历就是左中右形式。

二、map:

1、map介绍:

        map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素。它包含可以重复的键值对(key-value pairs),但每个键(key)在map中是唯一的。map提供了一种从键(key)映射到值(value)的方式,其中键用于唯一标识元素,而值是与该键相关联的数据。

特点:

  1. map中的元素总是按照键值key进行比较排序的。
  2. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序 对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  3. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  4. map和set一样会通过键值key去重操作。

2、常用构造:

void map1()
{map<string, int> m1; // 无参构造// 传入键值对构造map<string, int> m2 = { {"zhangsan",1 }, { "lisi",2 }, { "wangwu",3 } }; // 迭代器区间构造:vector<pair<string, int>> p = { {"zhangsan",1 }, { "lisi",2 }, { "wangwu",3 } };map<string, int> m3(p.begin(), p.end());map<string, int> m4(m3); // 拷贝构造map<string, int> m5 = m4; // 赋值重载// 遍历:for (auto e : m5){cout << e.first << " : " << e.second << endl;}
}

可以看到map默认以key值升序排序(也就是按照e.first升序排序)

3、常用修改操作:

(1)insert、emplace:

map的插入主要通过insert插入和emplace插入:

insert方法接受一个 pair<const Key, T>的值(或可以隐式转换为该值的对象),其中Key是键的类型,T是值的类型。

emplace方法则是直接在 map 中构造元素,而不是首先创建一个临时的pair对象。这通常可以减少不必要的拷贝或移动操作,从而提高效率。特别是当构造pair对象本身需要执行大量工作时(例如,当值类型涉及大量计算或内存分配时),使用emplace可以显著提高性能。

void map2()
{map<string, int> m1;m1["zhangsan"] = 1; m1["lisi"] = 2; m1["wangwu"] = 3; // 也可以通过此方法插入,底层的[]是重载了的map<string, int> m2;m2.insert(pair<string, int>("zhangsan", 1));m2.insert(make_pair("lisi", 2));// 上面的两种插入比较繁杂,所以一般使用以下简洁的写法m2.insert({ "wangwu",3 });m2.emplace("zhaoliu", 4);for (auto e : m2){cout << e.first << " : " << e.second << endl;}
}

(2)find:

find查找找到了返回指定key值位置的迭代器,找不到返回end();

(3)erase:

erase 的三种删除:

指定位置删除:m.erase(iterator)

指定区间删除:m.erase(first,second) 

指定key值删除:m.erase(key);

void map4()
{map<string, int> m;m["liuyi"] = 1; m["chener"] = 2; m["zhangsan"] = 3; m["lisi"] = 4; m["wangwu"] = 5; m["zhaoliu"] = 6;for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << endl;m.erase(m.begin());cout << "m.erase(iterator): erase(begin())" << endl;for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << endl;cout << "m.erase(key): key = zhangsan" << endl;;m.erase("zhangsan");for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << endl;cout << "erase(first,second): erase(begin(), end())" << endl;m.erase(m.begin(), m.end());for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << "因为进行begin() ~ end()的删除,所以map中已经没有元素" << endl;
}

4、其他操作:

(1)count:

count(key) 的操作就是在容器中查找是否有键值key,如果有返回1,没有返回0。

(2)lower_bound、upper_bound:

lower_bound(key_value)返回第一个大于等于key_value的定位器

upper_bound(key_value)返回第一个大于key_value的定位器

失败都返回end( );    可以理解为两者分别是一个开、闭区间【   )

void map7()
{map<string, int> m;m["liuyi"] = 1; m["chener"] = 2; m["zhangsan"] = 3;m["lisi"] = 4; m["wangwu"] = 5; m["zhaoliu"] = 6;for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << endl;// 同样可以配合erase达到删除区间的目的:m.erase(m.lower_bound("lisi"), m.upper_bound("zhansan"));for (auto& e : m){cout << e.first << " : " << e.second << endl;}cout << endl;
}

multimap:

        和multiset一样,取消了去重功能,可以加入重复key值的键值对,道理同前面讲multiset时的差不多,所以这里不再赘述。


http://www.ppmy.cn/news/1450007.html

相关文章

使用 uni-app 开发 iOS 应用的操作步骤

哈喽呀&#xff0c;大家好呀&#xff0c;淼淼又来和大家见面啦&#xff0c;上一期和大家一起探讨了使用uniapp开发iOS应用的优势及劣势之后有许多小伙伴想要尝试使用uniapp开发iOS应用&#xff0c;但是却不懂如何使用uniapp开发iOS应用&#xff0c;所以这一期淼淼就来给你们分享…

lxml 在 Windows 7上安装无法安装怎么办?

lxml 在 Windows 7上安装无法安装怎么办&#xff1f; 要在Windows 7上安装lxml&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装Python&#xff1a; 如果您的计算机尚未安装Python&#xff0c;请先安装Python。您可以从Python官方网站下载Windows安装程序&#xff0c…

细粒度数据设计对于微调的重要性

原文地址&#xff1a;the-importance-of-granular-data-design-for-fine-tuning 利用数据设计来训练LLM&#xff0c;以充分利用上下文&#xff0c;同时解决“Lost-In-The-Middle”的挑战。 2024 年 5 月 2 日 介绍 对话设计师难道不是杰出的数据设计师吗&#xff1f; 请允许我详…

本地大语言模型LLM的高效运行专家 | Ollama

Ollama简介 Ollama是一个开源的大型语言模型服务工具&#xff0c;它帮助用户快速在本地运行大模型。通过简单的安装指令&#xff0c;用户可以执行一条命令就在本地运行开源大型语言模型&#xff0c;如Llama 2。Ollama极大地简化了在Docker容器内部署和管理LLM的过程&#xff0…

ssh远程访问windows系统下的jupyterlab

网上配置这一堆那一堆&#xff0c;特别乱&#xff0c;找了好久整理后发在这里 由于既想打游戏又想做深度学习&#xff0c;不舍得显卡性能白白消耗&#xff0c;这里尝试使用笔记本连接主机 OpenSSH 最初是为 Linux 系统开发的&#xff0c;现在也支持包括 Windows 和 macOS 在内…

解决Blender导出FBX文件到Unity坐标轴错误的问题

发现Blender的模型导入到Unity里面有问题,简单研究了下发现是坐标系不同,Unity使用的是左手坐标系,Blender使用的是右手坐标系 。 下面直接将如何解决 首先忽略Blender的右手坐标系以及Z轴朝上的事&#xff0c;依照unity坐标系情况修改模型物体的旋转&#xff0c;以Blender猴…

C语言--贪吃蛇小游戏

目录 一、Win32API介绍 1.1Win32API 1.2控制台程序 1.3控制台屏幕上的坐标COORD 1.4GetStdHandle 1.5GetConsoleCursorInfo 1.6 CONSOLE_CURSOR_INFO 1.7 SetConsoleCursorInfo 1.8SetConsoleCursorPosition 1.9GetAsyncKeyState 二、贪吃蛇游戏设计与分析 2.1地图 …

单片机编程实例400例大全(100-200)

今天继续分享单片机编程实例第100-200例。 今天的实例会比前面100复杂一些&#xff0c;我大概看了下&#xff0c;很多都具备实际产品的参考价值。 今天继续分享单片机编程实例第100-200例。 今天的实例会比前面100复杂一些&#xff0c;我大概看了下&#xff0c;很多都具备实际…