【Java数据结构与算法】基础篇(6):哈希表

10 篇文章 0 订阅
9 篇文章 0 订阅

大家好,我是皮皮猫吖!

每文一言:别否定自己,你特别好,特别温柔,特别值得。


本篇文章:

主要是关于java数据结构与算法的一些基本知识:哈希表。

正文如下:

一、哈希表

1)哈希表的面试题

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

要求: 不使用数据库,尽量节省内存,速度越快越好 ==> 哈希表(散列)

2)散列表

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

简单的散列函数 (简单取余):长度为15的散列表,把id为111的放入到该散列表中,将111进行 % 15的操作,将111放到 111%15的这个链表中

在这里插入图片描述

3)哈希表相关的面试题:

① 问题:

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

② 要求:

1)不使用数据库的前提下,速度越快越好 ==> 选择使用哈希表(散列)

2)添加数据的时候,保证按照id从低到高插入 == 插入数据的时候,进行排序

3)使用链表来实现哈希表, 该链表不带表头[即: 链表的第一个结点就存放雇员信息]

4)代码实现[简单的增删改查(显示所有员工,按id查询)]

在这里插入图片描述

③ 代码如下:
package com.immort.dataStructure.hash;

import java.util.Objects;
import java.util.Scanner;

/**
 * 哈希表的相关代码
 * @author ppmy
 * @create 2021-04-03 18:09
 */
public class Study1HashTableDemo1 {
    public static void main(String[] args) {
        menu();
    }

    //菜单
    private static void menu(){
        HashTable hashTable = new HashTable(7);
        Scanner scanner = new Scanner(System.in);
        String key = "";
        int id;
        String name;
        Emp emp;
        while (true){
            System.out.println("add :添加数据");
            System.out.println("list:遍历链表");
            System.out.println("exit:退出程序");
            System.out.println("get :获取数据");
            System.out.println("del :删除数据");
            key = scanner.next();
            switch (key){
                case "add":
                    System.out.print("请输入id:");
                    id = scanner.nextInt();
                    System.out.print("请输入名字:");
                    name = scanner.next();
                    emp = new Emp(id, name,null);
                    hashTable.addEmp(emp);
                    break;
                case "list":
                    System.out.println("遍历当前哈希表:");
                    hashTable.listAll();
                    break;
                case "exit":
                    return;
                case "get":
                    System.out.print("请输入要获取数据的id:");
                    int idName = scanner.nextInt();
                    Emp emp1 = hashTable.getEmp(idName);
                    if(emp1!=null){
                        System.out.println(emp1);
                    }else{
                        System.out.println("该id数据不存在!");
                    }
                    break;
                case "del":
                    System.out.print("请输入要删除的数据id:");
                    id = scanner.nextInt();
                    boolean b = hashTable.deleteEmp(id);
                    if (b){
                        System.out.println("id为"+(id)+"的数据删除成功!");
                    }else{
                        System.out.println("该数据不在哈希表中,删除失败!");
                    }

            }

        }
    }
}

//存放EmpLinkedList的哈希表
//哈希表:存储多条链表
class HashTable{
    //哈希表
    private EmpLinkedList[] empLinkedListArr;

    //哈希表的大小:存放多少个链表
    private int size;

    //构造器:哈希表:存放size个链表
    public HashTable(int size){
        this.size = size;
        //创建一个size大小的哈希表
        empLinkedListArr = new EmpLinkedList[size];

        //创建每一个链表的头节点
        for (int i = 0; i < size; i++){
            empLinkedListArr[i] = new EmpLinkedList();
        }
    }

    //向对应的链表中添加数据
    public void addEmp(Emp emp){
        //根据员工的id,获取到该员工应该加入到哪一条链表
        int empLinkedListNum = hashFun(emp.getId());

        //将emp数据放到对应的链表中
        empLinkedListArr[empLinkedListNum].addEmp(emp);
    }

    //遍历所有的链表
    public void listAll(){
        for (int i = 0; i < empLinkedListArr.length;i++){
            //遍历当前链表中的数据,如果返回值为false
            if(!empLinkedListArr[i].listEmp(i)){
                System.out.println((i+1)+"链表为空!");
            }
        }
    }

    //编写一个散列函数
    private int hashFun(int id){
        return id % size;
    }

    public Emp getEmp(int id){
        return empLinkedListArr[id%size].getEmp(id);
    }

    //通过id删除数据
    public boolean deleteEmp(int id){
        return empLinkedListArr[id%size].deleteEmp(id);
    }


}

//存放emp的链表
class EmpLinkedList{
    private Emp head;

    public EmpLinkedList() {
    }

    public Emp getHead() {
        return head;
    }

    public void setHead(Emp head) {
        this.head = head;
    }

    //添加数据到链表中
    public void addEmp(Emp emp){
        //如果当前的head节点为null,表示链表为空,将当前节点置为头结点
        if(head==null){
            //将该节点置为头结点
            head = emp;
        }

        else{
            //获取到头结点
            Emp current = head;
            //遍历当前链表,遍历到按序排列的位置,添加数据
            while (current.getNext()!=null){
                if(current.getNext().getId()>emp.getId()){
                    emp.setNext(current.getNext());
                    current.setNext(emp);
                    return;
                }
                current = current.getNext();
            }

            if(current==head){
                if(current.getId()>emp.getId()){
                    emp.setNext(current);
                    head = emp;
                    return;
                }
            }

            //节点添加到当前链表的末尾处
            current.setNext(emp);

        }
    }

    //遍历当前链表
    public boolean listEmp(int i){
        //获取到头结点
        Emp current = head;
        //如果当前头结点为null,直接返回false
        if(current==null){
            return false;
        }
        //当前链表数据不为空
        //遍历当前链表
        System.out.println((i+1)+"链表的信息为:");
        while (current!=null){
            System.out.println(current);
            current = current.getNext();
        }
        return true;
    }

    //根据id查找指定Emp数据
    public Emp getEmp(int id){
        Emp current = head;

        while (current!=null){
            if(current.getId()==id){
                return current;
            }
            current = current.getNext();
        }
        return null;
    }

    //通过id删除emp数据
    public boolean deleteEmp(int id){
        Emp current = head;
        if(current==null){
            return false;
        }
        while (current!=null && current.getId()!=id){
            current = current.getNext();
        }

        if(current==head){
                head = current.getNext();
                return true;
        }

        return false;
    }
}

//emp数据
class Emp{
    private int id;
    private String name;
    //指向下一个emp节点
    private Emp next;

    public Emp() {
    }

    public Emp(int id, String name,Emp next) {
        this.id = id;
        this.name = name;
        this.next = next;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public void setNext(Emp next){
        this.next = next;
    }

    public Emp getNext(){
        return this.next;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Emp emp = (Emp) o;
        return id == emp.id && Objects.equals(name, emp.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


希望本篇文章对大家有所帮助,后续会继续分享java数据结构与算法相关学习知识…

如果文章内容有错误的地方,请在留言处留下你的见解,方便大家共同学习。谢谢!

如有侵权或其他任何问题请联系:QQ1370922071,本文主要用于学习交流,转载请声明!

作者:皮皮猫吖


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值