一、哈希表基本介绍

哈希表(Hash table,又称散列表),是根据关键码值(Key value)而直接进行访问的数据结构。其通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

实现哈希表的两种方法:

(1)数组+链表
(2)数组+红黑二叉树

二、哈希函数

哈希函数:建立起数据元素的存放位置与数据元素的关键字之间的对应关系的函数。即使用哈希函数可将被查找的键转换为数组的索引。理想情况下它应该运算简单并且保证任何两个不同的关键字映射到不同的单元(索引值)。但是很多时候我们都需要处理多个键被哈希到同一个索引值的情况,即哈希冲突。
以下是哈希函数的构造方法:
1、直接定址法
取关键字或关键字的某个线性函数值为哈希地址。即H(key)=key 或 H(key)=a*key+b (a,b为常数)。
2、数字分析法
若关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
3、平方取中法
取关键字平方后的中间几位为哈希地址。
4、折叠法
将关键字分割成位数相同的几部分(最后一部分的位数可不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。适用于关键字位数比较多,且关键字中每一位上数字分布大致均匀时。
5、除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址(p为素数),即H(key)=key MOD p,p<=m (最简单,最常用)p的选取很重要。一般情况,p可以选取为质数或者不包含小于20的质因数的合数(合数指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数)。
6、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址。即H(key)=random(key),其中random为随机函数。适用于关键字长度不等时。

三、哈希冲突解决

1、开放地址法
开放地址法:通过系统的方法找到系统的空位(三种:线性探测、二次探测、再哈希法),并将待插入的元素填入,而不再使用用hash函数得到数字作为数组的下标。

(1)线性探测:假若当前要插入的位置已经被占用了之后,沿数组下标递增方向查找,直到找到空位为止。
(2)二次探测:二次探测和线性探测的区别在于二次探测的步长是,若计算的原始下标是x则二次探测的过程是x+12,x+22,x+32,x+42,x+52随着探测次数的增加,探测的步长是探测次数的二次方(因此名为二次探测)。二次探测会产生二次聚集:即当插入的几个数经过hash后的下标相同的话,那么这一串数字插入的探测步长会增加很快。
(3)再hash法:为了消除原始聚集和二次聚集,把关键字用不同的hash函数再做一遍hash化,用过这个结果作为探测的步长,这样对于特定的关键字在整个探测中步长不变,但是不同的关键字会使用不同的步长。stepSize = constant - (key % constant) 这个hash函数求步长比较实用,constant是小于数组容量的质数。(注意:第二个hash函数必须和第一个hash函数不同,步长hash函数输出的结果值不能为0)。

2、链地址法
链地址法 :创建一个存放单词链表的数组,数组内不直接存放元素,而是存储元素的链表。发生冲突的时候,数据项直接接到这个数组下标所指的链表中即可。
优势:填入过程允许重复,所有关键值相同的项放在同一链表中,找到所有项就需要查找整个是链表,稍微有点影响性能。删除只需要找到正确的链表,从链表中删除对应的数据即可。表容量是质数的要求不像在二次探测和再hash法中那么重要,由于没有探测的操作,所以无需担心容量被步长整除,从而陷入无限循环中。

四、使用哈希表管理公司员工信息

1、题目

有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id, 性别, 年龄, 电话),当输入该员工的 id 时,要求查找到该员工的所有信息。

要求:
(1)不使用数据库,速度越快越好
(2)添加时,保证按照id从低到高插入
(3)使用链表来实现哈希表, 且链表不带表头

2、代码实现

package Hash;import java.util.Scanner;public class Hash {public static void main(String[] args) {hashtable hash=new hashtable(7);int n;Scanner sc=new Scanner(System.in);while(true) {System.out.println("1:  添加雇员");System.out.println("2:  显示雇员");System.out.println("3:  查找雇员");System.out.println("4:  退出系统");         n = sc.nextInt();switch (n) {case 1:System.out.println("输入id");int id = sc.nextInt();System.out.println("输入名字");String name = sc.next();System.out.println("输入性别");String sex = sc.next();System.out.println("输入电话");String phone = sc.next();Employee emp=new Employee(id,name,sex,phone);//创建员工hash.add(emp);break;case 2:hash.show();break;case 3:System.out.println("请输入要查找的员工id");id = sc.nextInt();hash.find(id);break;case 4:sc.close();System.exit(0);default:break;}  }}
}//员工类
class Employee{public int id;//员工idpublic String name;//员工名字public String sex;//员工性别public String phone;//员工电话public Employee next;//指向下一个员工指针,默认为nullpublic Employee(int id, String name,String sex,String phone) {//Employee的构造函数super();this.id = id;this.name = name;this.sex = sex;this.phone = phone;}
}//员工信息链表
class EmployeeList{private Employee head;//头指针,指向第一个Employee//添加员工public void add(Employee emp) {if(head==null) {//添加第一个员工head=emp;return;}Employee cur =head; //辅助指针while(true) {if(cur.next==null) {//链表已经到尾部break;}cur=cur.next;//cur后移继续遍历}cur.next=emp;//退出while循环时表示已经到链表尾,直接在链表尾部添加上员工}//遍历员工信息public void show(int no) {if(head==null) {System.out.println("第 "+(no+1)+" 条链表为空");return;}System.out.print("第 "+(no+1)+" 条链表的信息为");Employee cur =head; //辅助指针while(true) {System.out.printf(" => id=%d name=%s sex=%s phone=%s\t", cur.id, cur.name,cur.sex,cur.phone);//遍历一次输出信息一次if(cur.next == null) {//链表已经到尾部break;}cur=cur.next; //cur后移继续遍历}System.out.println();}//根据id查找员工public Employee find(int id) {if(head==null) {//空链表System.out.println("链表为空");return null;}Employee cur =head; //辅助指针while(true) {if(cur.id==id) {//找到id即退出while循环break;}if(cur.next==null) {//遍历完当前链表没有找到该员工cur=null;break;}cur=cur.next; //cur后移继续遍历}return cur;}
}//HashTable管理多条链表
class hashtable{private EmployeeList[] employeelist;private int size;//链表总数//hashtable的构造函数public hashtable(int size) {this.size=size;employeelist=new EmployeeList[size];//初始化employeelistfor(int i=0;i<size;i++) {employeelist[i]=new EmployeeList();}}//添加员工public void add(Employee emp) {int employeeNo=hashFun(emp.id);//根据员工的id,得到该员工应当添加到哪条链表employeelist[employeeNo].add(emp);//将emp 添加到对应的链表中}//遍历hashtablepublic void show() {for(int i=0;i<size;i++) {employeelist[i].show(i);}}//根据id查找员工public void find(int id) {//使用散列函数确定到哪条链表查找int employeeNo = hashFun(id);Employee emp = employeelist[employeeNo].find(id);if(emp!= null) {//找到System.out.printf("在第%d条链表中找到 雇员 id = %d name = %s sex = %s phone = %s", (employeeNo + 1), id,emp.name,emp.sex,emp.phone);System.out.println();}else{System.out.println("在哈希表中,没有找到该雇员~");}}//散列函数--除留余数法private int hashFun(int id) {return id%size;}
}

运行结果展示:

1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
1
输入id
1001
输入名字
Jack
输入性别
男
输入电话
111
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
1
输入id
1002
输入名字
Tom
输入性别
男
输入电话
222
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
1
输入id
1003
输入名字
Lucy
输入性别
女
输入电话
333
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
1
输入id
1008
输入名字
Simth
输入性别
男
输入电话
444
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
2
第 1 条链表的信息为 => id=1001 name=Jack sex=男 phone=111     => id=1008 name=Simth sex=男 phone=444
第 2 条链表的信息为 => id=1002 name=Tom sex=男 phone=222
第 3 条链表的信息为 => id=1003 name=Lucy sex=女 phone=333
第 4 条链表为空
第 5 条链表为空
第 6 条链表为空
第 7 条链表为空
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
3
请输入要查找的员工id
1002
在第2条链表中找到 雇员 id = 1002 name = Tom sex = 男 phone = 222
1:  添加雇员
2:  显示雇员
3:  查找雇员
4:  退出系统
4

哈希表--管理公司员工信息相关推荐

  1. mysql修改员工表_员工信息表 实现增删改查操作

    1 importos2 definquiry_system():3 welcome =''' 4 -----------员工信息查询系统------------5 操作说明:6 增加ADD:17 删除 ...

  2. 表单-员工信息登记表

    <!DOCTYPE html> <html><head><meta charset=utf-8" /><title>员工信息登记表 ...

  3. 散列表查找(哈希表)

    散列函数构造经常要考虑: 1.散列表的长度 2.关键字的长度 3.关键字的分布情况 4.计算散列函数所需的时间 5.记录的查找频率 一个"好"的散列函数应遵循一下两条原则 (1)函 ...

  4. (附源码)基于java的员工信息管理系统 毕业设计201524

    Springboot员工信息管理系统 摘 要 由于数据库和数据仓库技术的快速发展,企业员工信管理建设越来越向模块化.智能化.自我服务和管理科学化的方向发展.员工信息管理对处理对象和服务对象,自身的系统 ...

  5. C++ 哈希表查询_进入哈希函数结界的世界

    1. 前言 哈希表或称为散列表,是一种常见的.使用频率非常高的数据存储方案. 哈希表属于抽象数据结构,需要开发者按哈希表数据结构的存储要求进行 API 定制,对于大部分高级语言而言,都会提供已经实现好 ...

  6. springboot基于java的员工信息管理系统毕业设计源码201524

    Springboot员工信息管理系统 摘 要 由于数据库和数据仓库技术的快速发展,企业员工信管理建设越来越向模块化.智能化.自我服务和管理科学化的方向发展.员工信息管理对处理对象和服务对象,自身的系统 ...

  7. springboot+mysql+基于java的员工信息管理系统 毕业设计-附源码201524

    Springboot员工信息管理系统 摘 要 由于数据库和数据仓库技术的快速发展,企业员工信管理建设越来越向模块化.智能化.自我服务和管理科学化的方向发展.员工信息管理对处理对象和服务对象,自身的系统 ...

  8. 哈希表(Hash Table)原理及其实现

    原理 介绍 哈希函数构造 冲突处理 举例 拉链法 hash索引跟B树索引的区别 实现 原理 介绍 哈希表(Hash table,也叫散列表), 是根据关键码值(Key value)而直接进行访问的数据 ...

  9. 数据结构 - 哈希表(用数组+链表实现存储员工信息,添加增删查功能)

    package hashtab;import java.util.Scanner;public class HashTabDemo {public static void main(String[] ...

最新文章

  1. linux NF NR实例,awk中使用NR和FNR的一些例子
  2. Servlet监听器Listener
  3. python3语法错误python_[大数据]Python 3.x中使用print函数出现语法错误(SyntaxError: invalid syntax)的原因 - 码姐姐找文...
  4. ThinkPHP 数据库操作之数据表模型和基础模型 ( Model )
  5. python | 三种可变参数简述
  6. runtest的选项应用
  7. Cygwin 下载极速源推荐
  8. html链接word,word添加网址超链接方法
  9. 软件测试 学习之路 CSS (二)
  10. 作为评审人完成了对其他小组第一阶段成果的评价
  11. Docker---DockerFile搭建的最简单的jsp应用
  12. 月入30K 的电子工程师很常见吗,需要具备啥素质才配得上这个薪资
  13. Vmware Workstation 无法连接到虚拟机,请确保您有权运行该程序。
  14. 猫哥教你写爬虫 047--scrapy框架
  15. 高斯公式(三重积分和第二类曲面积分互相转换)
  16. 简单实现通讯录中文名字按拼音首字母排序
  17. CMWAP 和 CMNET 的区别是什么?
  18. 关于AP, MAP的一些理解
  19. 基于嵌入式的无线条码扫描仪系统的设计
  20. 视源股份(CVTE)亮相世界顶级计算机视觉盛会CVPR 2017

热门文章

  1. 宝塔 云服务器 外网无法访问 解决办法
  2. 【Kali】Kali linux 2021版本GVM无法启动解决方法
  3. 阿里云ACP认证有用吗?
  4. Cheat sheet -----几乎所有编程语言的速查表
  5. 爱普生Epson TM-T88III 打印机驱动
  6. html文本怎么打印出来,如何把一个html文件直接打印出来(200分)
  7. 使用python的虚拟环境virtualenv
  8. c语言电报,[编程入门]电报加密-题解(C语言代码)
  9. Android ROM开发(一)——Windows下Cygwin和Android_Kitchen厨房的安装
  10. Android ImageView 四个角自定义角度,以及角度的变换