哈希表(是数据结构不是算法)

哈希表(散列)-Google

哈希表的基本介绍

散列表(Hash table 也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度,这个映射函数叫做散列函数,存放记录的数组叫做散列表
下面的数组,变成了一个链表数组
在这里插入图片描述
我们的java程序向数据库查数据,但是太频繁会造成内存的开销和浪费资源,数据量过大的时候,速度也会变慢,压力也会很大.所有现在很多的公司有缓存层,现在缓存的产品有很多,redis,Memcache等,但是我们在一二十年前是没有缓存产品的,我们就是自己写的,用(1)哈希表
数组+链表
数组+二叉树
在这里插入图片描述
看一个实际的需求
有一个公司,当有新的员工来报道的时候,要求将该员工的信息加入(id,性别,年龄,住址),当输入该员工的id时,要求查到该员工的所有信息
要求:不要用数据库尽量节省内存,速度越快越好=>哈希表(散列)
添加时保证按照id从低到高的顺序插入.
每一个链表有一个头指针指向当前链表的第一个雇员!

在这里插入图片描述
代码如下

package com.atguigu.hashtab;

import java.util.Scanner;

public class HasshTabDemo {
    public static void main(String[] args) {
       //创建一个哈希表,假定有7条链表
        HashTab hashTab = new HashTab(7);

        //写一个简单的菜单测试
        String key="";
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("add.添加雇员");
            System.out.println("list,显示雇员");
            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.findEmpByIds(id);
                    break;
                case "exit":
                    scanner.close();
                    System.exit(0);
                default:
                    break;
            }
        }
    }
}
//开始创建HashTab 管理多条链表
class HashTab{
    private EmpLinkedList[]  empLinkedListsArray;
    private int size; //表示共有多少条链表
    //首先要一个构造器
    public HashTab(int size){
        this.size=size;
        //初始化我们empLinkedListsArray链表
        empLinkedListsArray=new EmpLinkedList[size];
        //这时不要忘记分别初始化我们的每一条链表(上面初始化的是怎个哈希表那个数组,
        // 下面初始化的是我们数组元素,因为我们的数组元素是链表组成的
        for(int i=0;i<size;i++){
            empLinkedListsArray[i]=new EmpLinkedList();
        }
    }

    //真正的添加雇员
    public void  add(Emp emp){
        //首先我要根据员工的id得到该员工应当添加到那条链表
        int empLinkedListNO=hashFun(emp.id);
        //将emp添加到对应的链表中
        empLinkedListsArray[empLinkedListNO].empAdd(emp);
    }

    //遍历所有的链表(我们的哈希表)
    public void list(){
        for(int i=0;i<size;i++){
            empLinkedListsArray[i].showList(i);
        }
    }

    //根据输入的id查找雇员
    public void findEmpByIds(int id){
        //使用散列函数确定到那条链表查找
      int empLinkedListNO=hashFun(id);
      Emp emp=empLinkedListsArray[empLinkedListNO].findEmpById(id);
      if(emp!=null){
          System.out.println("在第"+(empLinkedListNO+1)+"条链表中找到该雇员");
      }else {
          System.out.println("在哈希表中没有找到该雇员");
      }
    }

    //编写一个散列函数,使用一个简单的取模法来处理这个
    public int hashFun(int id){
        return id%size;
    }


}


//表示一个雇员
class Emp{
    public int id;
    public String name;
    public Emp next;//next 默认为null

    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的分配总是从小到大
     * 2,因此我们将该雇员直接加入到本链表的最后即可
     * @param emp
     */
    public void empAdd(Emp emp){
        //如果是添加这条链表的第一个雇员
        if(head==null){
            head=emp;//head直接指向employee就型
            return;
        }
        //如果不是第一个雇员,则使用一个辅助指针,帮助定位到最后
        Emp curEmp=head;
        while (true){
            if(curEmp.next==null) {//说明到了最后
                break;
            }
            curEmp=curEmp.next;//后移
        }
        //退出时候,直接减emp加入链表的最后
        curEmp.next=emp;
    }


    //遍历链表的雇员信息
    public void showList(int no){
        if(head==null){
            //说明链表为空,返回就像
            System.out.println();
            System.out.println("当前链表"+(no+1)+"为空");
            return;
        }
        System.out.print("当前链表"+(no+1)+"的信息为:");
        Emp curEmp=head;//辅助指针
        while (true){
            System.out.print("==>id="+curEmp.id+" name==>"+curEmp.name);
            if(curEmp.next==null){//说明curEmp已经是最后节点
                break;
            }
            curEmp=curEmp.next;//后移
        }
    }

    //根据ID查找雇员

    /**
     *
     * @param id
     * @return  找到返回Emp,没有找到返回空
     */
    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;
    }
}

上面的哈希表我们默认是添加到每一条链表的最后,但是我们还可以就是如果插入数据的时候id没有从小到大插入,但是又要是顺序的我们改怎么插入了.代码又是怎么样的呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Galaxy@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值