回顾总结之数据结构:5 哈希表

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

1 哈希表结构

哈希表的快速访问是通过散列函数+数组实现的,对于存入的每一个对象,散列函数会计算出一个值,作为放入位置的下标;在查找的时候,同样通过散列函数计算出下标,实现快速定位。对于拥有相同哈希值的不同元素,对应数组的同一下标,它们存放在同一链表中。哈希表中的元素分布比较均匀时,查询效率高。

以如下哈希表为例,假设数组大小 size = 5,散列函数计算方法为 value % size

存入 0 时,哈希值为 0%5 = 0,则存入数组中下标 0 的位置,且 0 作为该处链表的第一个节点;
存入 1 时,哈希值为 1%5 = 1,则存入数组中下标 1 的位置,且 1 作为该处链表的第一个节点;
.
.
.
存入 4 时,哈希值为 4%5 = 4,则存入数组中下标 4 的位置,且 4 作为该处链表的第一个节点;
存入 5 时,哈希值为 5%5 = 0,则存入数组中下标 0 的位置,该位置已经存入的有元素了,所以将 5 加入到该处链表的尾部。
其他元素同理。
在这里插入图片描述

2 代码实现

以学生节点为例,拥有 name 和 id 两个属性,hash 值通过 id 计算。

package com.datastructure.hashtable;

public class HashTable {
    
    
    //该数组存放学生链表
    private StuLinkedList[] stuLinkedList;
    //数组大小,也是哈希表大小
    private int size;

    HashTable(int size){
    
    
        this.size = size;
        stuLinkedList = new StuLinkedList[size];
        //对数组中每一个链表进行初始化
        for (int i=0; i<size; ++i) {
    
    
            stuLinkedList[i] = new StuLinkedList();
        }
    }

    //向哈希表中添加元素
    public void add(String name, int id) {
    
    
        //通过散列函数计算在数组中的位置
        int stuLinkedNum = hashFun(id);
        //将元素添加到对应位置的链表中
        stuLinkedList[stuLinkedNum].add(name, id);
    }

    //在哈希表中查找元素
    public Stu findStuById(int id) {
    
    
        //通过散列函数计算在数组中的位置
        int stuLinkedNum = hashFun(id);
        //在对应位置的链表中查找元素
        Stu stu = stuLinkedList[stuLinkedNum].findStuById(id);
        System.out.printf("id 为 %d 的学生", id);
        if (stu == null) {
    
    
            System.out.println("没有找到");
            return null;
        } else {
    
    
            System.out.printf("姓名为 %s", stu.name);
            return stu;
        }
    }

    public void show() {
    
    
        for(int i=0; i<size; ++i) {
    
    
            System.out.print("下标 " + i +", ");
            stuLinkedList[i].show();
        }
        System.out.println();
    }

    //哈希函数
    private int hashFun(int id) {
    
    
        return id % size;
    }
}

class StuLinkedList {
    
    
    //头指针,指向第一个 Student
    private Stu head;
    StuLinkedList() {
    
    
        this.head = null;
    }
    //向链表中添加元素
    public void add(String name, int id) {
    
    
        if(head == null) {
    
    
            head = new Stu(name, id);
            return;
        }
        Stu curStu = head;
        while (curStu.next != null) {
    
    
            curStu = curStu.next;
        }
        curStu.next = new Stu(name, id);
    }

    //在链表中查找元素
    public Stu findStuById(int id) {
    
    
        if (head == null) {
    
    
            System.out.println("链表为空");
            return null;
        }
        //遍历链表
        Stu curStu = head;
        while (curStu != null) {
    
    
            if (curStu.id == id) {
    
    
                return curStu;
            }
            curStu = curStu.next;
        }
        return null;
    }

    public void show() {
    
    
        if (head == null) {
    
    
            System.out.println("链表为空");
            return;
        }
        System.out.print("链表信息为:");
        Stu curStu = head;
        while (curStu != null) {
    
    
            System.out.printf("id = %d, name = %s ;\t", curStu.id, curStu.name);
            curStu = curStu.next;
        }
        System.out.println();
    }

}

//定义学生节点
class Stu {
    
    
    //学生姓名
    String name;
    //学生 id
    int id;
    Stu next;

    Stu() {
    
    
        this.name = null;
        this.id = id;
        this.next = null;
    }
    Stu(String name, int id) {
    
    
        this.name = name;
        this.id = id;
        this.next = null;
    }
}
public class HashTable {
    
    
    private StuLinkedList[] stuLinkedList;
    private int size;

    HashTable(int size){
    
    
        this.size = size;
        stuLinkedList = new StuLinkedList[size];
        //对数组中每一个链表进行初始化
        for (int i=0; i<size; ++i) {
    
    
            stuLinkedList[i] = new StuLinkedList();
        }
    }

猜你喜欢

转载自blog.csdn.net/hejnhong/article/details/125646979