1. 哈希表是一种数据结构,其由数组+链表或数组+二叉树构成。哈希表最大的特征是利用散列函数将关键码值进行映射,并根据关键码值进行直接访问。利用哈希表可以极大提高查找速度。

2. 哈希表的具体结构:

以数组+链表为例,哈希表包含一个由链表构成的数组,数组中每个元素是一条链表的头节点,如下图所示

Java编写哈希函数 java哈希表怎么用_哈希表

 3. 散列函数:散列函数是哈希表的关键,通过散列函数才能快速确定要查找的值位于哪一条链表。散列函数有很多种,目前只学了简单的取模法,日后再行补充。例如我们以int型的ID作为关键码值,则对ID进行取模,取模得到的值就是其所在的链表序号。例如链表数组长度为5(即共有五条链表),ID为7,取模为2,则该内容应存储于第3条链表中。

 

4. 哈希表的代码实现:

import java.util.Scanner;

public class HashTableTest {
    public static void main(String[] args) {
        HashTable testHasTab = new HashTable(7);
        testHasTab.add(new Employee(3,"张三"));
        testHasTab.add(new Employee(7,"张三"));
        testHasTab.add(new Employee(1,"张三"));
        testHasTab.add(new Employee(9,"张三"));
        Scanner scan = new Scanner(System.in);
        while(true){
            System.out.println("添加:输入add");
            System.out.println("显示:输入show");
            System.out.println("查找:输入find");
            System.out.println("退出系统:输入exit");
            String input = scan.next();
            switch (input){
                case "add":
                    System.out.println("输入ID");
                    int id = scan.nextInt();
                    System.out.println("输入姓名");
                    String name = scan.next();
                    testHasTab.add(new Employee(id,name));
                    break;
                case "exit":
                    break;
                case "show":
                    testHasTab.showTable();
                    break;
                case "find":
                    System.out.println("请输入ID");
                    int findId = scan.nextInt();
                    Employee emp = testHasTab.findEmpByID(findId);
                    System.out.println("您查找的用户信息:"+emp.getId()+"--"+emp.getName());
                    break;
                default:
                    break;
            }
        }
//        testHasTab.add(new Employee(1,"张三"));

    }
}

//创建HashTable,用于管理多条链表
class HashTable{
    private EmployeeLinkedList[] employeeLinkedListArray;
    private int size;//有多少条链表

    public HashTable(int size){
        this.size = size;
        employeeLinkedListArray = new EmployeeLinkedList[this.size];
        //链表数组中的每一条链表都需要单独初始化,否则会出现空指针异常
        for (int i = 0; i < size; i++) {
            employeeLinkedListArray[i] = new EmployeeLinkedList();
        }
    }

    //添加员工
    public void add(Employee emp){
        //利用散列函数判断该员工应该被添加到哪一条链表
        int employeeLinkedListNumber = hasFun(emp.getId());
        employeeLinkedListArray[employeeLinkedListNumber].addEmp(emp);

    }

    public Employee findEmpByID(int id){
        int employeeLinkedListNumber = hasFun(id);
        Employee emp = employeeLinkedListArray[employeeLinkedListNumber].findEmpByID(id);
        return emp;
    }

    public void showTable(){
        for (int i = 0; i < size; i++) {
            employeeLinkedListArray[i].showList(i);
        }
    }

    //编写散列函数,最简单的是取模法
    public int hasFun(int id){
        return id % size;
    }
}

class EmployeeLinkedList{
    private Employee head = new Employee(0,"");
    public void addEmp(Employee emp){
        Employee temp = head;
        while(temp.getNext() != null){
            if(temp.getNext().getId() > emp.getId()){
                emp.setNext(temp.getNext());
                break;
            }
            temp = temp.getNext();
        }
        temp.setNext(emp);
    }
    public void deleteEmp(int id){}
    public Employee findEmpByID(int id){
        Employee curEmp = head;
        while(curEmp.getId() != id){
            curEmp = curEmp.getNext();
        }
        if(curEmp.getId() == id){
            return new Employee(curEmp.getId(),curEmp.getName());
        }else{
            return null;
        }
    }
    public void showList(int no){
        if (head.getNext() == null){
            System.out.println("链表"+no+"为空");
            return;
        }
        Employee temp = head.getNext();
        System.out.println("链表"+no+"包含的信息:");
        while(temp!=null){
            System.out.print("=>"+temp.getId()+"--"+temp.getName());
            temp = temp.getNext();
        }
        System.out.println();
    }
}

class Employee{
    private int id;
    private String name;
    private Employee next;
    public Employee(){}
    public Employee(int id,String name){
        this.id = id;
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

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

    public Employee getNext() {
        return next;
    }

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

5. 学习哈希表中的教训与心得:

(1)哈希表在创建以后,必须对表中每一条链表进行单独的初始化,否则在后续调用哈希表时,会出现空指针异常。

(2)哈希表的关键在于散列函数,所以哈希表其实又称为散列表。在存储和查找时均需利用散列函数来对待存储的内容进行位置映射。