C++ Primer 第十一章 关联容器 重点解读

news2024/11/19 22:46:40

1 map自定义排序

#include <map>
#include <iostream>
#include <functional>
using namespace std;
int main() {
	function<bool(pair<int, int>, pair<int, int>)> cmp = [&](pair<int, int> p1, pair<int, int> p2) -> bool {
		return p1.second < p2.second;
	};
	map< pair<int, int>, int, decltype(cmp)> mp({ {{5, 1}, 2}, {{1, 7}, 3}, {{7, 3}, 2}, {{2, 2}, 1} },cmp);
	//map<pair<int, int>, int> mp = { {{5, 2}, 2}, {{1, 2}, 3}, {{7, 2}, 2}, {{2, 2}, 1} };
	for (auto& p : mp) {
		cout << p.first.first << ' ' << p.first.second << ' ' << p.second << '\n';
	}
}

map的类模板参数
在这里插入图片描述
map的构造函数
在这里插入图片描述

2 map/unordered_map的下标操作

2.1 at()

访问关键字为k的元素,带参数检查:若k不存在容器中,抛出一个out_of_range异常

2.2 下标运算符与解引用迭代器的区别

下标运算符:调用insert返回pair<iterator, bool>用返回的迭代器访问mapped_type

		V& operator[](const K& key) {
			pair<iterator, bool> ret = _t.insert(make_pair(key, V()));
			return ret.first->second;
		}

解引用迭代器返回pair<key_type, mapped_type>

2.3 对比vector与map的下标运算符

map<int, int> m;
m[0] = 1;

vector<int> v;
v[0] = 1;

2.4 对map使用find替代下标操作

使用下标操作有一个严重的副作用:如果关键字还未在map中,下标操作会插入一个具有给定关键字的元素(具体原因可以参考2.2节给出的代码),其值为0;

3 用lower_bound、upper_bound、equal_range查找multimap中的元素

  1. 用lower_bound与upper_bound锁定范围
//authoers的key为作者,mapped为书名
//search_item表示要查找的作者
for (auto beg = authors.lower_bound(search_item), end = authors.upper_bound(search_item); beg != end; ++beg) {
    cout << beg->second << endl;
}
  1. 用equal_range锁定范围

equal_range接受一个关键字,返回一个迭代器pair,若关键字存在,则第一个迭代器指向第一个与关键字匹配的元素,第二个迭代器指向最后一个匹配元素之后的位置。若未找到匹配元素,则两个迭代器都指向关键字可以插入的位置

for (auto pos = authors.equal_range(search_item); pos.first != pos.second; ++pos.first) {
    cout << pos.first.second << endl;   
}

4 将自定义类型作为无序容器的关键字

默认情况下,无序容器使用关键字类型的==运算符来比较元素,他们还使用一个hash<key_type>类型的对象(仿函数)来生成每个元素的哈希值。标准库为内置类型(包括指针)提供了hash模板,还为一些标准库类型,比如string和智能指针类型定义了hash。

那么如何定义关键字为自定义类型的无序容器呢?

4.1类模板特化

namespace std {
    template<>
    struct hash<Sales_data> {
        //用来散列一个无需容器的类型必须要定义下列类型
        typedef size_t result_type;
        typedef Sales_data argument_type;    //默认情况下,此类型需要operator==
        size_t operator()(const Sales_data& s) const {
            return hash<string>() (s.bookNo) ^      //构造匿名对象调用operator()返回一个哈希值
                   hash<unsigned>() (s.units_sold) ^ 
                   hash<double>() (s.revenue);
        }
    }
}  //关闭std命名空间

4.2 通过类模板传参

size_t hasher(const Sales_data& sd) {
    return hash<string>() (sd.isbn());
}
//如果类中定义了operator==则只需重载哈希函数
bool eqOp(const Sales_data& lhs, const Sales_data& rhs) {    
    return lhs.isbn() == rhs.isbn();
}
int main() {
	using SD_multiset = unordered_multiset<Sales_data, decltype(hahser)*, decltype(eqOp)*>;   //C++11
    
    //参数是桶大小、哈希函数指针和相等性判断运算符指针
    SD_multiset bookstore(42, hasher, eqOp);   
}

  • 为什么能通过上述代码完成自定义类型作为无序容器的关键字呢?
  1. 模板参数

在这里插入图片描述

以下是unordered_multiset类的成员类型,其中key_equal是typedef的第三个模板参数,该类创建的对象用于调用operator==比较两关键字是否相等。

member typedefinitionnotes
key_typethe first template parameter (Key)
mapped_typethe second template parameter (T)
value_typepair<const key_type,mapped_type>
hasherthe third template parameter (Hash)defaults to: hash<key_type>
key_equalthe fourth template parameter (Pred)defaults to: equal_to<key_type>
allocator_typethe fifth template parameter (Alloc)defaults to: allocator<value_type>
referenceAlloc::reference
const_referenceAlloc::const_reference
pointerAlloc::pointerfor the default allocator: value_type*
const_pointerAlloc::const_pointerfor the default allocator: const value_type*
iteratora forward iterator to value_type
const_iteratora forward iterator to const value_type
local_iteratora forward iterator to value_type
const_local_iteratora forward iterator to const value_type
size_typean unsigned integral typeusually the same as size_t
difference_typea signed integral typeusually the same as ptrdiff_t
  1. equal_to类模板的实现:

在这里插入图片描述

equal_to类在容器中创建的对象:key_eq(其他无序容器均有)
在这里插入图片描述
在这里插入图片描述

  1. 对于unordered系列的构造函数,都有一个接受unsigned int参数的构造函数,表示哈希桶的大小,且不能被隐式类型转换
    在这里插入图片描述

5 无序容器的管理操作

  • Buckets
    • bucket_count

      Return number of buckets (public member function)

    • max_bucket_count

      Return maximum number of buckets (public member function)

    • bucket_size

      Return bucket size (public member type)

    • bucket

      Locate element’s bucket (public member function)

    Hash policy
    • load_factor

      Return load factor (public member function)

    • max_load_factor

      Get or set maximum load factor (public member function )

    • rehash

      Set number of buckets (public member function )

    • reserve

      Request a capacity change (public member function)

#include <unordered_map>
#include <iostream>
using namespace std;
int main() {
	unordered_map<int, int> mp(8);
	cout << mp.bucket_count() << endl;    //output: 8
	mp.insert({ 1, 1 });
	mp.insert({ 2, 1 });
	mp.insert({ 3, 1 });
	mp.insert({ 11, 1 });
	for (int i = 0; i < 8; i++) {
		cout << mp.bucket_size(i) << ' ';     //output:0 0 0 0 1 0 2 1
	}
}

6 总结

  • 有序容器(set multiset map multimap)底层为红黑树,使用比较函数来比较关键字,从而将元素按顺序存储。默认情况下,比较操作是采用关键字类型的**<运算符(operator <)**

  • 无序容器(unordered_set unordered_multiset unordered_map unordered_multimap)底层是哈希桶,使用关键字类型的**==运算符(operator ==)和一个hash<key_type>类型的对象来计算哈希值从而组织对象(放入哪个哈希桶中)
    ,使用比较函数来比较关键字,从而将元素按顺序存储。默认情况下,比较操作是采用关键字类型的
    <运算符(operator <)
    *

  • 无序容器(unordered_set unordered_multiset unordered_map unordered_multimap)底层是哈希桶,使用关键字类型的**==运算符(operator ==)**和一个hash<key_type>类型的对象来计算哈希值从而组织对象(放入哪个哈希桶中)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1112308.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式-综合应用(一)

介绍 使用jQuery做一个模拟购物车的示例 用到的设计模式 工厂模式 单例模式装饰器模式 观察者模式状态模式 模板方法模式 代理模式 UML类图

leetcode - 319. Bulb Switcher

Description There are n bulbs that are initially off. You first turn on all the bulbs, then you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it’s off or turning off if it’s on). For the ith round, you toggl…

Apollo的搭建

Apollo的搭建 1.环境准备 jdk : 1.8 mysql 5.6.5 2.下载 两种方式&#xff1a; a.下载源码自己编译&#xff08;需要修改源码的可以选择&#xff09; 源码&#xff1a;https://github.com/ctripcorp/apoll b.编译好的直接使用 地址&#xff1a;Releases apol…

人人开源前后端分离开源项目启动流程(超详细)

renren-security是一个轻量级的&#xff0c;前后端分离的Java快速开发平台&#xff0c;能快速开发项目并交付【接私活利器】采用SpringBoot、Shiro、MyBatis-Plus、Vue3、TypeScript、Element Plus、Vue Router、Pinia、Axios、Vite框架&#xff0c;开发的一套权限系统&#xf…

Vue2基础知识(一) 认识Vue

&#x1f48c; 所属专栏&#xff1a;【Vue2】&#x1f600; 作 者&#xff1a;长安不及十里&#x1f4bb;工作&#xff1a;目前从事电力行业开发&#x1f308;目标&#xff1a;全栈开发&#x1f680; 个人简介&#xff1a;一个正在努力学技术的Java工程师&#xff0c;专注基础和…

原创!—混合灰狼层次结构的自适应麻雀搜索算法GWHASSA

麻雀搜索算法&#xff08;SSA&#xff09;是薛建凯等人[1]提出的一种群体智能优化算法,是受麻雀觅食和躲避捕食者行为启发而设计出的算法。该算法于2020年首次提出&#xff0c;具有局部搜索能力强、调整参数少等特点&#xff0c;已成功应用于CT图像的现场检测、电池堆参数的优化…

分布式和微服务

问题分析&#xff1a; 简单来说&#xff0c;分布式是一组通过网络进行通信&#xff0c;并且为了完成共同的计算任务的计算机节点组 成的系统。 分布式系统的设计理念&#xff0c;其实是来自于小型机或者大型机的计算能力的瓶颈和成本的 增加。 在集中式系统里面&#xff0c;要…

FL Studio21最新中文破解进阶高级完整版安装下载教程

目前水果软件最版本是FL Studio21&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破想象力的限制。喜欢音乐制作的小伙伴千万不要错过这个功能强大&#xff0c;安装便捷的音乐软件哦&#xff01;如…

ThreadLocal源码解密

1 背景 作为一只懒懒地程序员,其实我是不太爱看源码的,晦涩、深奥、难懂、耗费时间等等,就觉得不是我这种能力平平地小老百姓能吃得消的,但现实比人强,记得曾经我就被不懂原理的情况下乱用ThreadLocal给毒打了。 犹记得当时在一个JSF服务中的责任链的校验场景中需要在源…

使用vcpkg管理依赖第三库

文章目录 使用vcpkg管理依赖第三库vcpkg安装vcpkg经典模式使用从仓库列表搜索依赖项从某个基线版本的列表中查询某个依赖项信息安装依赖库 vcpkg清单模式的使用vcpkg清单模式的使用例子说明 使用vcpkg管理依赖第三库 vcpkg 有两种操作模式&#xff1a;经典模式和清单模式。 在…

36 机器学习(四):异常值检测|线性回归|逻辑回归|聚类算法|集成学习

文章目录 异常值检测箱线图z-score 保存模型 与 使用模型回归的性能评估线性回归正规方程的线性回归梯度下降的线性回归原理介绍L1 和 L2 正则化的介绍api介绍------LinearRegressionapi介绍------SGDRegressor 岭回归 和 Lasso 回归 逻辑回归基本使用原理介绍正向原理介绍损失…

深入理解JavaScript ES8的新特性

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

opencv改善pdf清晰度

improve-pdf 介绍&#xff1a; 使用python脚本对pdf进行优化&#xff0c;提高pdf清晰度&#xff0c;使文字更加清晰&#xff0c;观感更佳。仅适用黑白扫描版pdf&#xff0c;且文字较清晰&#xff0c;若模糊会更加模糊。 原理&#xff1a; pdf转成png图片 再使用opencv对图片…

【算法训练-回溯算法 三】【回溯算法最佳实践】括号生成、复原IP地址

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【回溯算法】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

由Django-Session配置引发的反序列化安全问题

漏洞成因 漏洞成因位于目标配置文件settings.py下 关于这两个配置项 SESSION_ENGINE&#xff1a; 在Django中&#xff0c;SESSION_ENGINE 是一个设置项&#xff0c;用于指定用于存储和处理会话&#xff08;session&#xff09;数据的引擎。 SESSION_ENGINE 设置项允许您选择不…

MSQL系列(六) Mysql实战-SQL语句优化

Mysql实战-SQL语句优化 前面我们讲解了索引的存储结构&#xff0c;BTree的索引结构&#xff0c;以及索引最左侧匹配原则&#xff0c;Explain的用法&#xff0c;可以看到是否使用了索引&#xff0c;今天我们讲解一下SQL语句的优化及如何优化 文章目录 Mysql实战-SQL语句优化1.…

统信uos 1030 企业版 安装.net core环境

安装.net core步骤 添加密钥和包存储库 安装 .NET 之前&#xff0c;请运行以下命令&#xff0c;将 Microsoft 包签名密钥添加到受信任密钥列表&#xff0c;并添加包存储库wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-mic…

nuxt使用i18n进行中英文切换

中文效果图&#xff1a; 英文效果图&#xff1a; 版本&#xff1a; 安装&#xff1a; npm install vue-i18n8.27.0 --savenpm i nuxtjs/i18n # npm 新建en.js与zh.js两个文件进行切换显示 en.js内容 import globals from ./../js/global_valexport default {/******* 公共内…

什么是软件测试? 软件测试都有什么岗位 ?软件测试和调试的区别? 软件测试和开发的区别?软件测试等相关概念入门篇

1、什么是软件测试&#xff1f; 常见理解&#xff1a; 软件测试就是找BUG&#xff0c;发现缺陷 真正理解&#xff1a; 软件测试就是验证软件产品特性是否满足用户的需求 测试定义&#xff1a; 测试人员验证软件是否符合需求的这个过程就是测试 2、为什么要有测试 标准情况下&a…

ShareMouse for Mac(多台电脑鼠标键盘共享软件)

ShareMouse mac版是一款Mac平台上可以在多台电脑间共享鼠标的工具软件&#xff0c;sharemousefor Mac支持 Windows 与 Mac&#xff0c;并可以在不同电脑间共享剪贴板。只需要移动鼠标指针的到想控制的显示器那里去、鼠标光标就会神奇地“跨越”到邻近的电脑屏幕上。每个计算机都…