哈希表介绍

一、什么是哈希表

1、哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为O(1),因为哈希表的查找速度非常快,所以在很多程序中都有使用哈希表,例如拼音检查器。

2、哈希表也有自己的缺点,哈希表是基于数组的,我们知道数组创建后扩容成本比较高,所以当哈希表被填满时,性能下降的比较严重。

3、哈希表是由链表和数组组成的:

        链表:增删的效率极高,但是查询的效率极低。

        数组:查询效率极高,增删效率低

        所以哈希表中继承了链表和数组的优缺点,不仅查询效率高,增删效率也高

4、哈希表通过键值对的方式存储数据,【key,value】,哈希表会通过散列函数/哈希函数将key转换成对应的数组下标。【采用 % 的方式】

哈希表介绍_第1张图片

二、哈希表的应用


    通常数据都是放在数据库中的,但是有一些数据不需要存放在数据库中 ,太麻烦,那么就需要我们使用缓存层
        缓存层一般有俩种:

            缓存产品或者自己写一个缓存层(也就是哈希表)

通过一个列子自己构建出哈希表:

看一个实际需求,google公司的一个上机题:

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

要求: 不使用数据库,尽量节省内存,速度越快越好

思路:

        1、首先要求不使用数据库,那么是能用一些缓存产品用来存储数据,所以需要构建一个哈希表

        2、哈希表有数组,链表组成。在链表中保存员工数据信息,数组中保存链表

  代码实现:

        1、创建员工类:定义员工的属性

//创建员工类
class Emp {
    int id ; // id
    String name; // 姓名
    String sex ; // 性别

    Emp next; //指向下一节点

    //构造器
    public Emp(int id, String name, String sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

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

 2、创建链表【如何创建之前有写】

//创建链表
class LinkList {
    //头结点
    Emp head = new Emp(0, "", "");

    //增加员工信息
    public void add(Emp emp) {
        Emp temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = emp;
    }

    //根据ID查询员工信息
    public Emp findByID(int id) {
        if (head.next == null) {
            System.out.println("空链表");
            return null;
        }
        Emp temp = head;
        while (true) {
            if (temp.id == id) {
                break;
            }
            temp = temp.next;
        }
        return temp;
    }

    //遍历员工信息
    public void show() {
        if (head.next == null) {
            System.out.println("该链表没有增加员工信息");
            return;
        }
        Emp temp = head.next;
        while (true) {
            System.out.println("ID = " + temp.id + ", name = " + temp.name + ", 性别 = " + temp.sex);
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
    }

    //根据ID删除员工信息
    public void del(int id) {
        if (head.next == null) {
            System.out.println("空链表");
            return;
        }
        boolean flag = false;
        Emp temp = head;
        while (true) {
            if (temp.next.id == id) { //找到删除节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
            System.out.println("删除成功");
        } else {
            System.out.println("没有找到删除节点");
        }
    }
}

3、创建哈希表

//创建哈希表
class HashTable {
    //链表的个数
    int size;
    //arr[0]:第一个链表 arr[1]:第二个链表
    LinkList[] arr;

    public HashTable(int size) {
        this.size = size;
        arr = new LinkList[size];

        //初始化数组中每个链表
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new LinkList();
        }
    }

    //散列函数--用来指明员工信息保存在哪个链表中
    public int function(int id) {
        return id % size;
    }

    //增加
    public void add(Emp emp) {
        //增加的emp在 第 i 个链表中
        int i = function(emp.id);
        //增加到对应的链表中
        arr[i].add(emp);
    }

    //遍历
    public void show() {
        for (int i = 0; i < size; i++) {
            arr[i].show();
        }
    }

    //通过id查询信息
    public Emp findByID(int id) {
        int i = function(id);
        return arr[i].findByID(id);
    }

    //删除
    public void del(int id) {
        int i = function(id);
        arr[i].del(id);
    }
}

    public int function(int id) {
        return id % size;
    }

这是一个简单的散列函数,哈希表通过这样的一个函数将关键值转换为对应的数组下标,并将数据存入链表中

4、测试

提供一个操作菜单:

     HashTable hashTable = new HashTable(7);

        //写一个简单的菜单
        String key = "";//接受用户输入
        Scanner scanner = new Scanner(System.in);
        boolean flag = true;
        while (flag) {
            System.out.println("输入:a 表示增加员工信息");
            System.out.println("输入:l 表示遍历员工信息");
            System.out.println("输入:e 表示退出程序");
            System.out.println("输入:f 表示 通过ID获取员工信息");
            System.out.println("输入:d 表示 通过ID删除员工信息");
            System.out.print("请输入关键字:");
            key = scanner.next();
            switch (key) {
                case "a":
                    System.out.println("请填写增加的数据:");
                    System.out.print("请输入ID:");
                    int id = scanner.nextInt();
                    System.out.print("请输入姓名:");
                    String name = scanner.next();
                    System.out.print("请输入性别:");
                    String sex = scanner.next();

                    Emp emp = new Emp(id, name, sex);
                    hashTable.add(emp);
                    break;
                case "l":
                    hashTable.show();
                    break;
                case "f":
                    System.out.print("请输入要查找员工的ID:");
                    int id1 = scanner.nextInt();
                    Emp emp1 = hashTable.findByID(id1);
                    System.out.println(emp1);
                    break;
                case "d":
                    System.out.print("请输入删除员工的ID:");
                    int id2 = scanner.nextInt();
                    hashTable.del(id2);
                    break;
                case "e":
                    scanner.close();
                    flag = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("您已经退出程序!");

测试结果

输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:a
请填写增加的数据:
请输入ID:1
请输入姓名:张三
请输入性别:男

输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:a
请填写增加的数据:
请输入ID:2
请输入姓名:李四
请输入性别:女

输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:l
该链表没有增加员工信息
ID = 1, name = 张三, 性别 = 男
ID = 2, name = 李四, 性别 = 女

该链表没有增加员工信息
该链表没有增加员工信息
该链表没有增加员工信息
该链表没有增加员工信息
输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:f
请输入要查找员工的ID:2
Emp{id=2, name='李四', sex='女'}

输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:d
请输入删除员工的ID:1
删除成功

输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:l
该链表没有增加员工信息
该链表没有增加员工信息
ID = 2, name = 李四, 性别 = 女
该链表没有增加员工信息
该链表没有增加员工信息
该链表没有增加员工信息
该链表没有增加员工信息
输入:a 表示增加员工信息
输入:l 表示遍历员工信息
输入:e 表示退出程序
输入:f 表示 通过ID获取员工信息
输入:d 表示 通过ID删除员工信息
请输入关键字:e
您已经退出程序!

你可能感兴趣的:(#,数据结构与算法,散列表,数据结构,哈希算法)