【算法】哈希映射(C/C++)

news2024/12/28 9:01:33

目录

算法引入:

算法介绍:

优点:

缺点:

哈希映射实现:

map

unordered_map

题目链接:“蓝桥杯”练习系统

解析:

 代码实现: 


哈希映射算法是一种通过哈希函数将键映射到数组索引以快速访问数据的数据结构。它的核心思想是利用哈希函数的快速计算能力,将键(Key)转换为数组索引,从而实现对数据的快速访问和存储。哈希映射在现代软件开发中非常重要,它提供了高效的数据查找、插入和删除操作。

算法引入:

小白算法学校今年经过了层层考核,预选拔了六名队员,这六名队员的信息如下,好巧不巧的是这六名队员有重名的,叫张三的有两个人,叫李四的有两个人。那么教练如何区分它们呢,只叫队员的名字很可能叫错人,这是不被认可的叫法,根据下标去叫张三,可是真正的张三都不知道自己的下标是哪一个。欣慰的时,每一名队员都有一个学号,学号是唯一的值,每一名队员的学号都不一样,那么教练可以直接说出学号的值,那么就可以锁定唯一的那一位队员了,此时去用下标对应学号,那么唯一的下标值对应唯一且不重复的学号,那么这就是叫做哈希映射,下标被称为“键”,学号被称为“值”。

下标姓名学号
0张三100
1李四101
2王五102
3赵六103
4张三107
5李四108

算法介绍:

哈希映射在绝大部分题目中使用的频率还是比较高的,它主要的思想就是键值映射,通过一个整数也就是下标值,在一个数组里面有且仅有一个唯一的值与之对应,有点类似于经过去重的数组一样,但是这种映射是有规律可循的。

哈希映射的工作原理依赖于哈希函数,哈希函数接受一个键作为输入,并返回一个值,这个整数通常用作数组的索引。理想情况下,哈希函数应该将输入均匀分布到所有可能的索引值上,以减少不同键映射到同一个索引值的情况,即“哈希碰撞”。

当发生哈希碰撞时,有几种常见的解决策略

1. 链地址法:每个数组元素不直接存储键值对,而是存储一个链表。当多个键通过哈希函数映射到同一索引时,这些键值对将被存储在同一个链表中。
2. 开放寻址法:当发生哈希碰撞时,哈希映射会尝试找到数组中的下一个空闲位置,按照某种系统的方式(如线性探测)进行。

优点:

哈希映射的优点就是数据操作增删改查,增加、删除、查找操作的时间复杂度接近O(1)。它还支持动态扩容,以适应数据量的增加。

缺点:

哈希映射也有一些缺点,比如哈希碰撞虽然可以减少但无法完全避免,需要通过额外的数据结构或探测算法来解决。此外,为了减少哈希碰撞,哈希表可能会预留较大的空间,导致内存利用率不是很高。

哈希映射实现:

哈希映射实现方式一般都是通过map来实现,map就类似上述的功能,可以说是一个数组,但是里面的下标可以是数字、字符、字符串、pair、结构体等,这些下标去映射值,值也有可能数字、字符、字符串、pair、结构体等,map內部的实现自建一颗红黑树,map的查询、插入、删除操作的时间复杂度都是O(logn)。map默认按照key进行升序排序,和输入的顺序无关。 如果是int/double等数值型为key,那么就按照大小排列;如果是string类型,那么就按照字符串的字典序进行排列。

map

在使用map时,需要加入头文件#include<map>,下面解析一下map常用的函数:

1.insert

insert是插入函数,在指定的下标位置插入键值映射。

mymap.insert(mymap.begin(),pair<char,int>('a',1));//指定位置插入
mymap.insert(pair<char,int>('a',1));//直接插入键值对
mymap.insert({{'a',1},{'b',2}});//多键值对插入
//相当于mymap['a']=1;

2.find

find为查找函数,如果查找到则返回迭代器指向当前查找元素的位置,否则查找不到返回map.end()位置。

map<char,int>::iterator it=mymap.find('a');//查找关键字为'a'的迭代器位置

3.erase
erase是删除函数,能够对指定位置进行删除键值,也可以根据键进行删除,或者通过迭代器进行删除。

map<char,int>::iterator it=mymap.find('a');//查找关键字为'a'的迭代器位置
mymap.erase(it);//对map容器的第二个位置进行删除键值映射
mymap.erase('a');//删除('a',1)键值映射,删除成功能找到'a'的键,返回1,否则返回0
mymap.erase(mymap.begin(),mymap.end());//删除整个map容器,功能相当于clear

4.clear

clear函数则是清空函数,对整个map容器进行清空,里面不再有键值映射关系。

mymap.clear();

5.遍历 

map的遍历有很多种,但是最常见的还是迭代器遍历,迭代器遍历非常方便,可以很好的操作map容器,其次使用range遍历,前提是C++11的编译器,其特点是简洁。

	map<char,int>::iterator iter;
	for(iter=mymap.begin();iter!=mymap.end();iter++){//迭代器遍历
		cout<<iter->first<<" "<<iter->second;
	}
	for(auto it1:mymap){//range遍历
		cout<<it1.first<<" "<<it1.second;
	}

其他
下面是C++ map其他的一些函数。

     begin()         返回指向map头部的迭代器
     end()           返回指向map末尾的迭代器
     count()         返回指定元素出现的次数,因为key值不会重复,所以非0即1
     empty()         判空,map为空则返回true
     max_size()      返回可以容纳的最大元素个数
     rbegin()        返回一个指向map尾部的逆向迭代器
     rend()          返回一个指向map头部的逆向迭代器
     size()          返回map中元素的个数
     swap()          交换两个map里面的键值
     upper_bound()   返回键值>给定元素的第一个位置
     lower_bound()   返回键值>=给定元素的第一个位置
     value_comp()    返回比较元素value的函数
     key_comp()      返回比较元素key的函数

#include<iostream>
#include<map>
using namespace std;
map<char,int> mymap;
int main(){
	mymap.insert(mymap.begin(),pair<char,int>('a',1));//指定位置插入
	mymap.insert(pair<char,int>('a',1));//直接插入键值对
	mymap.insert({{'a',1},{'b',2}});//多键值对插入
	//相当于mymap['a']=1;
	map<char,int>::iterator it=mymap.find('a');//查找关键字为'a'的迭代器位置
	mymap.erase(it);//对map容器的第二个位置进行删除键值映射
	mymap.erase('a');//删除('a',1)键值映射,删除成功能找到'a'的键,返回1,否则返回0
	mymap.erase(mymap.begin(),mymap.end());//删除整个map容器,功能相当于clear
	
	map<char,int>::iterator iter;
	for(iter=mymap.begin();iter!=mymap.end();iter++){//迭代器遍历
		cout<<iter->first<<" "<<iter->second;
	}
	for(auto it1:mymap){//range遍历
		cout<<it1.first<<" "<<it1.second;
	}
	
	if(!mymap.empty()){//empty函数
		cout<<1<<endl;
	}
	map<char,int> youmap;
	swap(mymap,youmap);//swap函数 map交换
	
	if(!mymap.count('a')){//count函数
		cout<<1<<endl;
	}
	
	auto it2=mymap.lower_bound(1);//lower_bound函数
	
	map<char,int>::key_compare comp = mymap.key_comp();//key_comp()函数
    bool result = comp('a', 'b');
    cout <<result<<endl;  // 输出 1 (true)

	return 0;
}

unordered_map

unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value。不同的是unordered_map不会根据key的大小进行排序,存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的。unordered_map的底层是一个防冗余的哈希表(开链法避免地址冲突)。unordered_map用到自定义的类型,需要对key定义hash_value函数并且重载operator == 哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,时间复杂度为O(1),函数基本都一样。

题目链接:“蓝桥杯”练习系统

问题描述

  给定2维平面上n个整点的坐标,一条直线最多能过几个点?

输入格式

  第一行一个整数n表示点的个数
  以下n行,每行2个整数分别表示每个点的x,y坐标。

输出格式

  输出一个整数表示答案。

样例输入

5
0 0
1 1
2 2
0 3
2 3

样例输出

3

数据规模和约定

  n<=1500,数据保证不会存在2个相同的点。
  点坐标在int范围内

解析:

这是妥妥的map的映射啊,这个是斜率double类型去映射int类型的直线点的个数,用哈希表关键字与键值映射即可,斜率当关键字,每有一个点在此直线上不断加一即可。话不多说,直接上代码,代码附注释。


 代码实现: 

#include<iostream>
#include<utility>
#include<map>
 
using namespace std;
 
pair<int,int> a[2000];//输入二维坐标,用pair或结构体
int n,maxx;
 
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].first>>a[i].second;//输入位置
    }
    map<double,int> p;//用map映射
    for(int i=0;i<n;i++){//始点
        for(int j=i+1;j<n;j++){//终点
            double k;//斜率
            k=double(a[i].second-a[j].second)/(a[i].first-a[j].first);//强转为double,否则数据会四舍五入
            if(p[k]==0){//如果此次斜率是第一次出现,说明两点构成一条直线,点数为2,需要多加一次
                p[k]++;
            }
            p[k]++;//如果存在了那就再此基础上加一即可
            maxx=max(p[k],maxx);//寻找最大值
        }
        p.erase(p.begin(),p.end());//暴力枚举,若不清空,会影响下一个始点的计算
        //我们是先固定起点,再遍历终点,求斜率
        //若有三个点构成一条直线,第一次固定第一个点为始点,终点遍历后面两个点,此时为点数3
        //若不清空继续遍历,第二个点为始点,第三个点为终点,p[k]++还会继续,变为4,重复计算,所以清空
    }
    cout<<maxx<<endl;
    return 0;
}

哈希映射算法应用的场景还是非常多的,博主在参加第十五届蓝桥杯国赛的时候,80%的题目都用到了map映射,博主感觉国赛考察map映射能力去处理、解决问题还是比较重要的。执笔至此,感触彼多,全文将至,落笔为终,感谢各位的支持。

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

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

相关文章

JAVA基础语法 Day11

一、Set集合 Set特点&#xff1a;无序&#xff08;添加数据的顺序和获取出的数据顺序不一致&#xff09;&#xff0c;不重复&#xff0c;无索引 public class demo1 {public static void main(String[] args) {//1.创建一个集合//HashSet特点&#xff1a;无序&#xff0c;不重…

Redis: 集群架构,优缺点和数据分区方式和算法

集群 集群指的就是一组计算机作为一个整体向用户提供一组网络资源 我就举一个简单的例子&#xff0c;比如百度&#xff0c;在北京和你在上海访问的百度是同一个服务器吗&#xff1f;答案肯定是不是的&#xff0c;每一个应用可以部署在不同的地方&#xff0c;但是我们提供的服务…

C0010.Qt5.15.2下载及安装方法

1. 下载及安装 Qt 添加链接描述下载地址&#xff1a;http://download.qt.io/ 选择 archive 目录 安装Qt **注意&#xff1a;**本人使用的是Qt5.15.2版本&#xff0c;可以按如下方法找到该版本&#xff1b;

华为OD机试 - 信号发射和接收 - 矩阵(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

【AIGC】AI时代的数据安全:使用ChatGPT时的自查要点

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;法律法规背景中华人民共和国保守秘密法中华人民共和国网络安全法中华人民共和国个人信息保护法遵守法律法规的重要性 &#x1f4af;ChatGPT的数据使用特点ChatGPT数据安全…

华为OD机试 - 分班问题(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

无人机电力巡检:点亮电力巡检新视野!

一、无人机电力巡查的优势 提高巡检效率&#xff1a;无人机可以搭载高清摄像头、红外热像仪等先进设备&#xff0c;实时拍摄和传输图像&#xff0c;帮助巡检人员快速发现潜在问题&#xff0c;如电线破损、绝缘子污损、设备过热等&#xff0c;从而大大缩短了巡检周期。 降低人…

Tiny Transformer:从零开始构建简化版Transformer模型

引言 自然语言处理&#xff08;NLP&#xff09;与计算机视觉&#xff08;CV&#xff09;有显著差异&#xff0c;各自任务的独特性决定了它们适用的模型架构。在CV中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;长期占据主导地位&#xff0c;而在NLP领域&#xff0c;循…

基于微信小程序的四六级词汇+ssm(lw+演示+源码+运行)

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;四六级词汇小程序被用户普遍使用&#xff0c;为方便用户能…

Python入门--判断语句

目录 1. 布尔类型和比较运算符 2. if语句的基本格式 3. if-else语句 4. if-elif-else语句 5. 判断语句的嵌套 6. 应用--猜数字游戏 进行逻辑判断&#xff0c;是生活中常见的行为。同样&#xff0c;在程序中&#xff0c;进行逻辑判断也是最为基础的功能。 1. 布尔类型和比…

OceanBase—02(入门篇——对于单副本单节点,由1个observer扩容为3个observer集群)——之前的记录,当初有的问题未解决,目前新版未尝试

OceanBase—02&#xff08;入门篇——对于单副本单节点&#xff0c;由1个observer扩容为3个observer集群&#xff09;——之前的记录&#xff0c;有的问题未解决&#xff0c;新版未尝试 1、前言—安装单副本单节点集群1.1 docker安装OB 2、查看现有集群情况2.1 进入容器&#x…

设置服务器走本地代理

勾选&#xff1a; 然后&#xff1a; git clone https://github.com/rofl0r/proxychains-ng.git./configure --prefix/home/wangguisen/usr --sysconfdir/home/wangguisen/etcmakemake install# 在最后配置成本地代理地址 vim /home/wangguisen/etc/proxychains.confsocks4 17…

Python编写的贪吃蛇小游戏

安装包 pip install pygame完整代码 import pygame import randompygame.init()# 定义颜色 white (255, 255, 255) black (0, 0, 0) red (213, 50, 80) green (0, 255, 0) blue (50, 153, 213)# 定义屏幕大小 dis_width 800 dis_height 600dis pygame.display.set_mo…

【数据结构】什么是平衡二叉搜索树(AVL Tree)?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;AVL树的概念 &#x1f4cc;AVL树的操作 &#x1f38f;AVL树的插入操作 ↩️右单旋 ↩️↪️右左双旋 ↪️↩️左右双旋 ↪️左单旋 &#x1f38f;AVL树的删…

CTF刷题buuctf

[WUSTCTF2020]颜值成绩查询 拿到相关题目&#xff0c;其实根据功能和参数分析。需要传入一个学号然后进行针对于对应的学号进行一个查询&#xff0c;很可能就会存在sql注入。 其实这道题最难的点&#xff0c;在于过滤了空格&#xff0c;因此我们使用 /**/来过滤空格的限制。…

智能化焊接数据管理系统:系统功能设计与应用场景,OEM定制

在快速发展的工业4.0时代&#xff0c;智能化技术正以前所未有的速度改变着各行各业&#xff0c;其中焊接行业也不例外。随着物联网、大数据、人工智能等技术的不断融合&#xff0c;智能化焊接数据管理系统应运而生&#xff0c;成为提高焊接效率、保障焊接质量、优化生产流程的重…

半监督学习与数据增强(论文复现)

半监督学习与数据增强&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 半监督学习与数据增强&#xff08;论文复现&#xff09;概述算法原理核心逻辑效果演示使用方式 概述 本文复现论文提出的半监督学习方法&#xff0c;半监督学习&…

C题(二)字符串转数字 --- atoi

———————————————————**目录**—————————————————— 一、 atoi函数介绍 功能函数原型使用示例 二、题解之一 三、留言 问题引入&#x1f449; 输入样例&#x1f449; 5 01234 00123 00012 00001 00000 输出样例&#x1f449; 1234 123 …

‌文件名称与扩展名:批量重命名的技巧与指南

在日常的文件管理中&#xff0c;我们经常需要处理大量的文件&#xff0c;这些文件可能有着各种各样的名称和扩展名。为了更好地管理和识别这些文件&#xff0c;批量重命名成为了一项非常实用的技能。能够帮助我们快速整理文件&#xff0c;提高工作效率。本文将深入探讨文件名称…

vue2圆形标记(Marker)添加点击事件不弹出信息窗体(InfoWindow)的BUG解决

目录 一、问题详情 二、问题排查 三、解决方案 一、问题详情 地图上面的轨迹点希望能通过点击看到详细的经纬度信息&#xff0c;但是点击的时候就是显示不出来。 二、问题排查 代码都是参考高德的官方文档&#xff0c;初步看没有问题啊&#xff0c;但是点击事件就感觉失效…