《算法笔记》总结No.4——散列

        散列的英文名是hash,即我们常说的哈希~该知识点在王道408考研的教材里面属于查找的范围。即便各位并无深入了解过,也听说过散列是一种更高效的查找方法。


一.引例

先来考虑如下一个假设:设有数组M和N分别如下:

M[10]=[1,2,3,4,5,6,7,8,9,10];

N[10]=[11,12,13,14,15,16,17,18,19,20];

        M和N都是大小为10的一维数组。现在要求判断M中的整数是否在N中出现过,那么最简单暴力的一个办法就是把M中的每一个元素都在N中遍历一遍,由于M和N都是10个,因此一共要执行100次。

        不难发现——上述操作主打一个繁琐:当M和N的长度均为10000时,则需要操作1亿次——毫无疑问这是不可取的,且不说总量有多大,如果有相同的数出现,岂不是做了很多重复的步骤? 

        因此不妨考虑用空间换取时间:新开辟一个数组hashTable[10000],用来表示N中的元素是否存在——存在时即为true,不存在则赋值为false。这样如果一开始的时候就将N遍历一遍,把hashTable中的元素赋值后,M直接在hashTable中查找元素是否存在即可!


听起来有些抽象,那么举个例子直观感受一下:就拿长度为10的M和N举例:

#include <iostream>
#include <cstdio> 
using namespace std;
  
bool hashTable[10000]={ false };
//一开始所有元素均为false——不存在 
int main(int argc, char** argv) {
	//第一个循环直接用来保存N 
	for(int i=1;i<=10;i++)
	{
		int temp=0;
		cin>>temp;
		hashTable[temp]=true; //输入的元素标识为存在 
	}
	for(int i=1;i<=10;i++)
	{
		int temp=0;
		cin>>temp;
		if(hashTable[temp]==true)   //如果true即为存在 
			cout<<temp<<"在N中出现过!"<<endl; 
		else
			cout<<temp<<"在N中没出现!"<<endl;
	}
}

测试结果如下:

        来分析一下:由于存放和查找是两个独立的循环,复杂度为n+n即为2n——在这里为20。 相比暴力搜索这种100的量级还是便捷了不少,事实上当出现重复元素时可以进一步细分~

扩展:如果此处要求统计出现的次数,直接将类型改为int,然后赋值为true变成自增即可

        不难发现,上述引例中,是将元素直接作为下标来标记的——即7出现N[7]变为true,25出现N[25]变为true。这当然是非常实用且巧妙的一种做法。当下标超出、或者是元素为abcde时,这种方法就不凑效了。这时候就需要我们的散列~ 

二.整数散列

        散列的本质或者说定义可以浓缩为一句话:将元素通过一个函数转换为一个整数,使得该整数可以尽量唯一的代表这个元素。这个转换函数被称为散列函数~


常见的散列函数取法:

  • 直接定址法:恒等变换(即将key的值作为下标值),线性变换(x=a*key+b)。
  • 平方取中法:很少用,即取key值平方的中间若干位作为hash值。
  • 除留取余法: 很常用,即H(key)=key%mod,通过这种散列函数,可以把很大的数转换为不超过mod的整数,这样就可以将他作为可行的数组下标!不过表长TSize一定要大于mod,不然显而易见会发生越界。此外,当mod是一个素数时,显而易见空间可以尽可能的覆盖下标的值。为了方便起见,一般来说mod的值与TSize相等。

        当然,很明显会存在两个不同的key1和key2——他们的哈希值H(key1)、H(key2)有可能是相同的,当其中一个占领了目标单元格,另一个显而易见不能使用——这种情况被称之为冲突。以下为三种解决冲突的常见方法:

1.开放定址法

A.线性探测法

        当目标的H(key)被占领时,直接检查下一个位置即H(key)+1上的位置是否被占,如果还被占就继续寻找n+1,以此类推;如果超过了表长,就回到首位继续循环,直到所有位置都被占用。该种方法会导致扎堆,会一定程度上降低效率。

B.平方探测法

为了避免扎堆现象,发生冲突后将依次查找如下位置:H(key)+1^2,H(key)-11^2,H(key)+2^2,以此类推。如果超出表长,则对表长完成取模;如果为负数,则对结果不断加表长直到出现第一个非负数。

如果在0~TSize范围内都无法找到位置,当k大于表长时,也一定无法找到位置。

2.链地址法(拉链法) 

不计算新的hash值,而是把所有H(key)相同的key连接成一条单链表。

三.字符串散列

给出N个由3位大写字母组成的字符串,再给出M个查询字符串,问每个字符串在N个字符串中出现的次数。

#include <iostream>
#include <cstdio> 
using namespace std;
  
const int maxn=100;
char S[maxn][5],temp[5];
int hashTable[26*26*26+10];

int hashFunc(char S[],int len)
{
	int id=0;
	for(int i=0;i<len;i++)
		id=id*26+(S[i]-'A');
	return id;	
} 

int main(int argc, char** argv) {
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		int id=hashFunc(S[i],3);
		hashTable[id]++;
	}
	for(int i=0;i<m;i++)
	{
		cin>>temp;
		int id=hashFunc(temp,3);
		cout<<hashTable[i]<<endl;
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring AOP 源码解析前篇】什么是 AOP | 通知类型 | 切点表达式| AOP 如何使用

前言&#xff08;关于源码航行&#xff09; 在准备面试和学习的过程中&#xff0c;我阅读了还算多的源码&#xff0c;比如 JUC、Spring、MyBatis&#xff0c;收获了很多代码的设计思想&#xff0c;也对平时调用的 API 有了更深入的理解&#xff1b;但过多散乱的笔记给我的整理…

自动化设备上位机设计 四

目录 一 设计原型 二 后台代码 一 设计原型 二 后台代码 using SimpleTCP; using SqlSugar; using System.Text;namespace 自动化上位机设计 {public partial class Form1 : Form{SqlHelper sqlHelper new SqlHelper();SqlSugarClient dbContent null;bool IsRun false;i…

【机器学习实战】Datawhale夏令营:Baseline精读笔记2

# AI夏令营 # Datawhale # 夏令营 在原有的Baseline上除了交叉验证&#xff0c;还有一种关键的优化方式&#xff0c;即特征工程。 如何优化特征&#xff0c;关系着我们提高模型预测的精准度。特征工程往往是对问题的领域有深入了解的人员能够做好的部分&#xff0c;因为我们要…

链式二叉树oj题

1.输入k &#xff0c;找第k层节点个数 int TreeKlevel(BTNode*root,int k) {if (root NULL) {return 0;}if (k 1) {return 1;}return TreeKlevel(root->left, k - 1)TreeKlevel(root->right, k - 1); } 在这里我们要确定递归子问题&#xff0c;第一个就是NULL时返回&…

强化学习中的Q-Learning和Sarsa算法详解及实战

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种通过与环境交互来学习最优策略的机器学习方法。在强化学习中&#xff0c;Q-Learning和Sarsa是两种重要的基于值的算法。本文将详细讲解这两种算法&#xff0c;并通过实际代码示例展示其应用。 1. 强化学习基…

algorithm算法库学习之——不修改序列的操作

algorithm此头文件是算法库的一部分。本篇介绍不修改序列的操作函数。 不修改序列的操作 all_ofany_ofnone_of (C11)(C11)(C11) 检查谓词是否对范围中所有、任一或无元素为 true (函数模板) for_each 应用函数到范围中的元素 (函数模板) for_each_n (C17) 应用一个函数对象到序…

Vue88-Vuex中的mapActions、mapMutations

一、mapMutations的调用 此时结果不对&#xff0c;因为&#xff1a;若是点击事件不传值&#xff0c;默认传的是event&#xff01;&#xff0c;所以&#xff0c;修改如下&#xff1a; 解决方式1&#xff1a; 解决方式2&#xff1a; 不推荐&#xff0c;写法麻烦&#xff01; 1-…

排序算法简述(第八jiang)

目录 排序 选择排序 O(n2) 不稳定&#xff1a;48429 归并排序 O(n log n) 稳定 插入排序 O(n2) 堆排序 O(n log n) 希尔排序 O(n log2 n) 图书馆排序 O(n log n) 冒泡排序 O(n2) 优化&#xff1a; 基数排序 O(n k) 快速排序 O(n log n)【分治】 不稳定 桶排序 O(n…

【图解大数据技术】Flume、Kafka、Sqoop

【图解大数据技术】Flume、Kafka、Sqoop FlumeFlume简介Flume的应用场景 KafkaKafka简介Kafka架构Flume与Kafka集成 SqoopSqoop简介Sqoop原理sqoop搭配任务调度器实现定时数据同步 Flume Flume简介 Flume是一个数据采集工具&#xff0c;多用于大数据技术架构下的日志采集。 …

设计模式之模版方法

模版方法介绍 模版方法&#xff08;Template Method&#xff09;模式是一种行为型设计模式&#xff0c;它定义了一个操作&#xff08;模板方法&#xff09;的基本组合与控制流程&#xff0c;将一些步骤&#xff08;抽象方法&#xff09;推迟到子类中&#xff0c;使得子类可以在…

C语言下的文件详解

主要内容 文件概述文件指针文件的打开与关闭文件的读写 文件 把输入和输出的数据以文件的形式保存在计算机的外存储器上&#xff0c;可以确保数据能随时使用&#xff0c;避免反复输入和读取数据 文件概述 文件是指一组相关数据的有序集合 文件是存储数据的基本单位&#…

# mysql 中文乱码问题分析

mysql 中文乱码问题分析 一、问题分析&#xff1a; MySQL 中文乱码通常是因为字符集设置不正确导致的。MySQL 有多种字符集&#xff0c;如 latin1、utf8、utf8mb4 等&#xff0c;如果在创建数据库、数据表或者字段时没有指定正确的字符集&#xff0c;或者在插入数据时使用了与…

关于Java异常机制及finally关键字的详解

异常机制(Exception) 软件程序在运行过程中&#xff0c;非常可能遇到异常问题。常见的异常&#xff1a; 1、用户输入错误 2、设备错误 3、硬件问题&#xff0c;例如打印机关掉、服务器问题 4、物理限制&#xff1a;磁盘满了 Java是采用面向对象的方式来处理异常的。 处理过程…

哈希表——C语言

哈希表&#xff08;Hash Table&#xff09;是一种高效的数据结构&#xff0c;能够在平均情况下实现常数时间的查找、插入和删除操作。 哈希表的核心是哈希函数&#xff0c;哈希函数是一个将输入数据&#xff08;通常称为“键”或“key”&#xff09;转换为固定长度的整数的函数…

使用vue3-treeselect问题

1.当vue3-treeselect是单选时&#xff0c;使用watch监听绑定value&#xff0c;无法监听到值清空 对照后将:value改为v-model&#xff0c;如图 2.使用vue3-treeselect全部清空按钮如何置空select的值&#xff0c;使用watch监听 多选&#xff1a;pageInfo.officeName(val) {// …

【Linux进阶】文件系统6——理解文件操作

目录 1.文件的读取 1.1.目录 1.2.文件 1.3.目录树读取 1.4.文件系统大小与磁盘读取性能 2.增添文件 2.1.数据的不一致&#xff08;Inconsistent&#xff09;状态 2.2.日志式文件系统&#xff08;Journaling filesystem&#xff09; 3.Linux文件系统的运行 4、文件的删…

Java--方法重写

1.方法的重写首先需要有继承关系&#xff0c;且为子类重写父类的方法 2.方法名必须相同 3.参数列表必须相同 4.修饰符的范围可以扩大但不能缩小&#xff0c;public>protected>default>private,即父类的属性可以从private改为public&#xff0c;但不能反过来 5.抛出…

python爬虫入门(四)之Beautiful Soup库

一、什么是Beautiful Soup库 1、Beautiful Soup库是用来做HTML解析的库 Beautiful Soup把看起来复杂的HTML内容&#xff0c;解析成树状结构&#xff0c;让搜索和修改HTML结构变得更容易 2、第三方库&#xff0c;先安装 终端输入pip install bs4 from bs4 import Beautiful…

Cyber Weekly #14:WAIC 2024

赛博新闻 1、WAIC2024开幕&#xff1a;一半机器人&#xff0c;一半大模型 7月4日&#xff0c;AI界春晚——2024世界人工智能大会&#xff08;WAIC 2024&#xff09;在上海开幕&#xff0c;大会展示了500家企业的1500项展品&#xff0c;突出了机器人和大模型技术。国产机器人和…

【排序算法】—— 快速排序

快速排序的原理是交换排序&#xff0c;其中qsort函数用的排序原理就是快速排序&#xff0c;它是一种效率较高的不稳定函数&#xff0c;时间复杂度为O(N*longN)&#xff0c;接下来就来学习一下快速排序。 一、快速排序思路 1.整体思路 以升序排序为例&#xff1a; (1)、首先随…