【数据结构】哈希表(散列表)
创始人
2024-11-13 16:36:40
0
介绍

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

哈希表的实际应用

Java 程序操作数据最普通的方式是直接操作数据库,经过一番操作后数据库将结果返回给程序,但是这种结构对数据库的操作非常频繁,造成了不必要的开销。

为了解决这个问题,我们可以在程序与数据库之间添加一个缓存层,把常用的数据加载到缓存层,这样就可以在缓存层中取数据,避免了对数据库的操作。

在缓存层,我们可以使用一些常见的缓存产品,如 Redis 、Memcache 等,但是这些缓存产品太重量级了,我们也可以使用哈希表来自己写一个缓存层,即先把数据存入哈希表,使用时从哈希表中取出数据。

 我们可以使用 数组+链表 来实现一个哈希表,结构如下

使用哈希表管理雇员信息

public class HashTabDemo {     public static void main(String[] args) {         //创建一个哈希表         HashTab hashTab = new HashTab(7);         //写一个简单菜单         String key;         Scanner scanner = new Scanner(System.in);         while (true) {             System.out.println();             System.out.println("add:添加雇员");             System.out.println("list:显示雇员");             System.out.println("find:查找雇员");             System.out.println("exit:退出系统");             key = scanner.next();             switch (key) {                 case "add":                     System.out.println("输入 id ");                     int id = scanner.nextInt();                     System.out.println("输入名字");                     String name = scanner.next();                     //创建雇员                     Emp emp = new Emp(id, name);                     hashTab.add(emp);                     break;                 case "list":                     hashTab.list();                     break;                 case "find":                     System.out.println("请输入要查找的id");                     id = scanner.nextInt();                     hashTab.findEmpById(id);                     break;                 case "exit":                     System.out.println("程序退出");                     scanner.close();                     System.exit(0);                 default:                     break;             }         }     } }  //表示一个雇员 class Emp {     public int id;     public String name;     public Emp next;  // next 默认为空      public Emp(int id, String name) {         super();         this.id = id;         this.name = name;     } }  //创建 EmpLinkedList ,表示链表 class EmpLinkedList {     //头指针,指向第一个 Emp ,因此我们这个链表的 head 是直接指向第一个 Emp     private Emp head;  //默认为空      //添加雇员到链表     /*     说明     1.假定当添加雇员时,id 是自增长的,即 id 的分配总是从小到大的     因此我们将该雇员直接加入本链表的最后即可      */     public void add(Emp emp) {         //如果是添加第一个雇员         if (head == null) {             head = emp;             return;         }         //如果不是添加第一个雇员,则使用一个辅助的指针,帮助定位到最后         Emp curEmp = head;         while (true) {             if (curEmp.next == null) {  //说明链表到最后                 break;             }             curEmp = curEmp.next;  //后移         }         //退出时直接将 emp 加入链表         curEmp.next = emp;     }      //遍历链表的雇员信息     public void list(int no) {         int tempNo = no + 1;         if (head == null) {  //说明链表为空             System.out.println("第" + tempNo + "条链表为空");             return;         }         System.out.print("第" + tempNo + "条链表的信息为:");         Emp curEmp = head;  //辅助指针         while (true) {             System.out.printf(" =>  id=%d name=%s\t", curEmp.id, curEmp.name);             if (curEmp.next == null) {                 break;             }             curEmp = curEmp.next;  //后移,遍历         }         System.out.println();     }      //根据 id 查找雇员     //如果查找到,就返回 Emp,如果没有找到,就返回 null     public Emp findEmpById(int id) {         //判断链表是否为空         if (head == null) {             System.out.println("链表为空");             return null;         }         //辅助指针         Emp curEmp = head;         while (true) {             if (curEmp.id == id) {  //找到                 break;  //这时 curEmp 就指向查找的雇员             }             //退出             if (curEmp.next == null) {  //说明遍历当前链表没有找到该雇员                 curEmp = null;                 break;             }             curEmp = curEmp.next;  //以后         }         return curEmp;     } }  //创建 HashTab 管理多条链表 class HashTab {     private EmpLinkedList[] empLinkedListArray;     private int size;  //表示共有多少条链表      //构造器     public HashTab(int size) {         this.size = size;         //初始化 empLinkedListArray         empLinkedListArray = new EmpLinkedList[size];         //不要忘记分别初始化每个链表!!!         for (int i = 0; i < size; i++) {             empLinkedListArray[i] = new EmpLinkedList();         }     }      //编写一个散列函数,使用一个简单取模法     public int hashFun(int id) {         return id % size;     }      //添加雇员     public void add(Emp emp) {         //根据员工的 id ,得到该员工应该添加到哪条链表         int empLinkedListNO = hashFun(emp.id);         //将 emp 添加到对应的链表中         empLinkedListArray[empLinkedListNO].add(emp);     }      //遍历所有链表,遍历 HashTab     public void list() {         for (int i = 0; i < size; i++) {             empLinkedListArray[i].list(i);         }     }      //根据输入的 id 查找雇员     public void findEmpById(int id) {         //使用散列函数确定到哪条链表查找         int empLinkedListNO = hashFun(id);         Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);         if (emp != null) {  //找到             System.out.printf("在第%d条链表中找到雇员id=%d", (empLinkedListNO + 1), id);         } else {             System.out.println("在哈希表中没有找到该雇员");         }     } }

相关内容

热门资讯

三分钟了解!微友破解器辅助插件... 三分钟了解!微友破解器辅助插件下载,新西部挂透视辅助,办法教程(有挂方法)-哔哩哔哩1)微友破解器辅...
据通报!微信小程序哥哥打大a辅... 据通报!微信小程序哥哥打大a辅助器(辅助)确实是有辅助辅助器(有挂透视)-哔哩哔哩1、首先打开微信小...
第7分钟了解!天道联盟辅助软件... 第7分钟了解!天道联盟辅助软件,渝都麻将开挂方法,方式教程(真的有挂)-哔哩哔哩一、渝都麻将开挂方法...
此事迅速冲上热搜!皮皮衡阳字牌... 此事迅速冲上热搜!皮皮衡阳字牌黑科技(辅助)都是存在有辅助app(有挂技巧)-哔哩哔哩1、下载好皮皮...
第4分钟了解!葫芦娃手游辅助脚... 第4分钟了解!葫芦娃手游辅助脚本,一起宁德钓蟹作z弊,妙计教程(有挂方法)-哔哩哔哩1)葫芦娃手游辅...
刚刚!全托中至窝龙拿好牌(辅助... 刚刚!全托中至窝龙拿好牌(辅助)本来有辅助软件(有挂解密)-哔哩哔哩一、全托中至窝龙拿好牌游戏安装教...
9分钟了解!微友联盟辅助,三加... 9分钟了解!微友联盟辅助,三加一辅助,技法教程(讲解有挂)-哔哩哔哩微友联盟辅助是不是有人用挂微扑克...
最新消息!泸州大二新手攻略(辅... 最新消息!泸州大二新手攻略(辅助)确实是真的辅助神器(有挂方针)-哔哩哔哩1、泸州大二新手攻略透视辅...
第六分钟了解!边锋辅助器,新西... 第六分钟了解!边锋辅助器,新西部外卦辅助器,指南书教程(有挂详细)-哔哩哔哩1、首先打开新西部外卦辅...
现有关情况通报如下!微信小程序... 现有关情况通报如下!微信小程序中至上饶麻将有挂(辅助)切实真的是有辅助修改器(有挂详细)-哔哩哔哩1...