【数据结构】哈希表(散列表)
创始人
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("在哈希表中没有找到该雇员");         }     } }

相关内容

热门资讯

透视app!aapoker怎么... 透视app!aapoker怎么设置抽水(透视)可以开辅助器(一贯是真的有挂)一、aapoker怎么设...
透视教程!哈糖大菠萝软件下载,... 透视教程!哈糖大菠萝软件下载,wepoker脚本(透视)原先有挂(科技教程)透视教程!哈糖大菠萝软件...
透视总结(WPK)确实有挂(透... 透视总结(WPK)确实有挂(透视)wpk辅助软件(攻略方法);1、wpk辅助软件透视辅助简单,wpk...
透视挂!pokernow辅助工... 透视挂!pokernow辅助工具,哈糖大菠萝怎么挂,真是是真的有挂(攻略教程)1、任何哈糖大菠萝怎么...
透视辅助!aapoker辅助工... 透视辅助!aapoker辅助工具安全吗(透视)发牌逻辑(总是有挂)1、超多福利:超高返利,海量正版游...
透视私人局!hh poker插... 透视私人局!hh poker插件下载,约局吧德州真的有透视挂吗(透视)起初存在有挂(技巧教程)1、构...
透视透视(WPK)切实真的有挂... 透视透视(WPK)切实真的有挂(透视)wpk有作弊吗(攻略方法)1)wpk有作弊吗辅助挂:进一步探索...
透视攻略!epoker有透视吗... 透视攻略!epoker有透视吗,拱趴大菠萝机器人,其实有挂(新2025教程);1、下载好拱趴大菠萝机...
透视科技!aapoker公共底... 透视科技!aapoker公共底牌(透视)辅助器是真的(竟然是有挂)1、每一步都需要思考,不同水平的挑...
透视好友!wepoker有没有... 透视好友!wepoker有没有挂,hhpoker辅助软件(透视)起初是真的有挂(解密教程)1、hhp...