ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Hash相关(从哈希表到哈希查找)

2022-07-11 22:04:52  阅读:158  来源: 互联网

标签:Hash 哈希 int 表到 关键字 地址 查找 key


        第一节——初赛中的Hash

        哈希表,也称散列表,是一种高效的数据结构。它的最大优点就是把数据存储和查找所消耗的时间大大降低,几乎可以看成是O(1)的,而代价是消耗比较多的内存。在当前竞赛可利用内存空间越来越多、程序运行时间控制的越来越近的情况下,“空间换时间”的做法还是很值得的。

        哈希冲突,不能保证每个元素的关键字与函数值是一一对应的,这样就产生了“冲突”。

        解决冲突方法:

        1、直接取余数法      h(k)=k  mod  m     //m一般为一个大素数

              关键字k除以m,取余数作为在Hash表中的位置。

        2、乘积取整法;

        3、平方取中法;

        4、线性探测法

        5、链地址法(后两种会在后面详细讲到,第二种和第三种可以自行了解,不强求)

 

        查找算法

        基本的查找算法有以下4种:

                1、线性查找(挨个看呗)

                2、二分查找(log级别每次折半查找,前提是所有元素必须是顺序排列的)

                3、分块查找(块与块有序、块内无序,可以理解成块外用二分、块内用线性)

                4、哈希查找(他来了,他来了!!)

        哈希查找简介

                1、哈希是Hash的音译,意译就是散列。哈希查找是一种按关键字地址的快速检索方法。

                2、哈希与其他查找方法的不同之处

                        (1)哈希查找是对记录的关键字值进行某种运算,直接求出记录的地址

                        (2)快——关键字到地址直接转换,无序反复比较

                        (3)核心不在于如何“比较”,而在于如何“计算”

                        (4)最能体现计算机科学精髓的查找方法

        哈希查找的基本思想:记录关键字与其存储地址之间的映射关系H(key),把某个较大的集合P映射到另一个较小的集合Q中,核心就是设计哈希函数,并构建哈希表。

        哈希查找过程:

                1、由给定的关键字key,根据哈希函数计算出对应的哈希地址H(key)

                2、根据H(key)直接找到该记录的存储位置

        哈希冲突与解决(系不系很多童鞋们都肥肠期待!!??)

        当两个不同的数据的哈希值相同时,就会发生冲突(collision)

        处理哈希冲突的常用方法之一:链地址法

        链地址法具体步骤:

                (1)将哈希值相同的数据存在一个链表中

                (2)查找哈希表时,当查找到这个链表时必须采用线性查找方法

        哈希函数典型构造方法——求模取余法

                (1)H(key)=key % p

                (2)p<=m,哈希表表长为m

                (3)余数(哈希地址)总是循环出现,呈周期性变化

        哈希表的特点

哈希表与一般的线性表的区别
一般的线性表 哈希表

在记录的存储地址与它的关键字之间不存在确定的对应关系

在记录的存储地址和它的关键字之间存在一个确定的对应关系

在表中查找记录时,需要进行一系列 的关键字比较

每个关键字在表中有唯一的一个存储地址与之对应,直接由关键字找到存储地址

建立在“比较“的基础上,查找效率依赖于查找过程中所进行的比较次数

 

根据关键字直接计算出记录存放的地址查找效率高

 

 

 

 

 

 

 

 

 

 

        第二节——Hash查询代码实现

        哈希典型题

        哈希构造的链表中查询方式比较快。已知存在一个随机的数据表(表中数字均为正整数,没有重复),数据个数n≤50000;现在给定一些整数,查询在表中是否存在。

        二分代码实现(代码短,时间长)

 

#include<iostream>
#include<algorithm>
using namespace std;

int a[10005],l,r,mid;

int main()
{
	int key,n,m;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a,a+n+1);
	while(m--)
	{
		cin>>key;
		l=1;
		r=n;
		while(l<=r)
		{
			mid=(l+r)/2;
			if(a[mid]==key)
			{
				cout<<"yes\n";
				break;
			}
			if(a[mid]<key)
			{
				l=mid+1;
			}
			if(a[mid]>key)
			{
				r=mid-1;
			}
		}
		if(a[mid]!=key)
		{
			cout<<"no\n";
		}
	}
	return 0;
}

 

  哈希代码实现(代码长、时间短)

#include<iostream>
using namespace std;

const int N=50000;
const int b=999979,H=999979;
int tot,adj[H],nxt[N],num[N];
int top,stk[N];

void init()
{
	tot=0;
	while(top)
	{
		adj[stk[top--]]=0;
	}
}

void insert(int key)
{
	int h=key%b;
	for(int e=adj[h];e;e=nxt[e])
	{
		if(num[e]==key)
		{
			return ;
		}
	}
	if(!adj[h])
	{
		stk[++top]=h;
	}
	nxt[++tot]=adj[h],adj[h]=tot;
	num[tot]=key;
}

bool query(int key)
{
	int h=key%b;
	for(int e=adj[h];e;e=nxt[e])
	{
		if(num[e]==key)
		{
			return true
		}
	}
	return false;
}

int main()
{
	int a[10000];
	init();
	int n,m;
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		cin>>a[i];
		insert(a[i]);
	}
	cin>>m;
	int num;
	for(int i=1;i<=m;i++)
	{
		cin>>num;
		if(query(num))
		{
			cout<<"yes"<<endl;
		}
		else
		{
			cout<<"no"<<endll;
		}
	}
	return 0;
}

  第三节——哈希冲突解决

        1、顺序寻址法

        设H(key)=key%9

        若当前位置已经有原先的数据了,则放到下一个位置去,如果下一个位置仍然不为空,那么久继续往后走,直到找到第一个为空的元素位置把该元素放进去。

        代码实现

int hash_table[N];
void push1(int x)
{
	int y=x%N;
	for(;hash_table[y]&&hash_table[y]!=x;)
	{
		y=(y+1)%N;
	}
	if(hash_table[y])
	{
		cout<<x<<"_has_occured_before!"<<endl;
	}
	else
	{
		hash_table[y]=x;
		cout<<x<<"_inserted."<<endl;
	}
}

  2、链地址法(刚才说过了,不再多说了,直接上代码)

        代码实现(用到了动态数组vector,在STL里面,不知道的可以去百度上搜搜教程)

 

        推荐题目(洛谷):P1102、P3370、P2957、P1955、P13381、P5018

 

标签:Hash,哈希,int,表到,关键字,地址,查找,key
来源: https://www.cnblogs.com/YZYc/p/Hash-class-YPPAH.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有