哈希表

一:什么是哈希表

哈希表是基于数组来实现的一种数据结构,提高了快速的插入和查找操作

二:哈希化

1.直接将关键字作为索引(关键字是数字类型)
2.将单词转换成索引(关键字是string类型)
2.1将字母转换成ASCII码,然后进行相加
存在风险: 比如: key1=abc , ,key2=bbb ;key1和key2通过将字母转化成ascii码后相加的值相等
2.2幂的连乘
127^2 + 227^1 + 3*27^0 … (27代表26个字母加一个空格 , 1代表第一个字母,2代表第二个字母…)
存在风险: 1.数组索引太大,造成空间浪费 ;
2.索引越界(大于int / long类型的界限)
2.3压缩可选值
把幂连乘的结果对数组长度取模,再把取模后的结果当成索引存进数组中
使用BigInteger类型代替int/long类型,避免幂连乘的结果越界
存在风险: 1.取模后会出现重复值,导致存进去数组的数据被覆盖掉 ;

三:压缩后任然可能出现的问题

冲突: 不能保证每个单词都映射到数组的空白单元
解决办法:
1.开放地址法
2.链地址法

四:代码实现

1.关键字作为索引

1.1创建JavaBean

public class Person {
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
    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;
    }
}

1.2创建HashTable

public class HashTable {
    //数组
    private Person[] arr;

    //构造
    public HashTable() {
        arr = new Person[10];
    }
    public HashTable(int size){
        arr = new Person[size];
    }

    //插入数据
    public void insert(Person person){
        //将关键字 id 作为数组的索引
        arr[person.getId()] = person;
    }

    //查找数据
    public Person find(int id){
        return arr[id];
    }
}

1.3测试

public class Test {
    public static void main(String[] args) {

        HashTable hashTable = new HashTable();

        //插入数据
        hashTable.insert(new Person(1,"张三"));
        hashTable.insert(new Person(2,"李四"));
        hashTable.insert(new Person(3,"王五"));

        //查找
        Person person = hashTable.find(2);
        System.out.println(person.getName());
    }
}

2.将字母转化成ASCII码然后相加作为索引

2.1创建JavaBean

public class Person {
    private String key;
    private String name;

    public Person(String key, String name) {
        this.key = key;
        this.name = name;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2.2创建HashTable

public class HashTable {
    //数组
    private Person[] arr;

    //构造
    public HashTable() {
         arr = new Person[10];
    }
    public HashTable(int size){
        arr = new Person[size];
    }

    //插入数据
    public void insert(Person person){
        //将关键字key 进行hash化后进行求和再作为索引
        arr[hashCode(person.getKey())] = person;
    }

    //查找数据
    public Person find(String key){
        return arr[hashCode(key)];
    }

    //字符串转化成ASCII码,并且进行相加
    public int hashCode(String key){
        int hashCode = 0;
        for (int i = key.length()-1;i>= 0 ; i--){
            int value = key.charAt(i) - 96;
           hashCode += value;
        }
        return hashCode;
    }
}

2.3测试

public class Test {
    public static void main(String[] args) {

        HashTable hashTable = new HashTable();

        //插入数据
        hashTable.insert(new Person("abc","张三"));
        hashTable.insert(new Person("bcd","李四"));
        hashTable.insert(new Person("bbb","王五"));

        //查找
        Person person = hashTable.find("abc");  //王五
        System.out.println(person.getName());

         person = hashTable.find("bbb"); //王五
        System.out.println(person.getName());

        //风险:  abc 的hashCode  = bbb 的hashCode

    }
}
3.幂的连乘

3.1创建JavaBean

public class Person {
    private String key;
    private String name;

    public Person(String key, String name) {
        this.key = key;
        this.name = name;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

3.2创建HashTable

public class HashTable {
    //数组
    private Person[] arr;

    //构造
    public HashTable() {
        arr = new Person[10000];
    }

    public HashTable(int size){
        arr = new Person[size];
    }

    //插入数据
    public void insert(Person person){
        //将关键字key 进行hash化后进行求和再作为索引
        arr[hashCode(person.getKey())] = person;
    }

    //查找数据
    public Person find(String key){
        return arr[hashCode(key)];
    }

    //字符串转化成ASCII码,并且进行幂的连乘
    public int hashCode(String key){
        int hashCode = 0;
        for (int i = key.length()-1;i>= 0 ; i--){
            int value = key.charAt(i) - 96;
            int sum = value*27^(key.length() - value);
           hashCode += sum;
        }
        return hashCode;
    }
}

3.3测试

public class Test {
    public static void main(String[] args) {

        HashTable hashTable = new HashTable();

        //插入数据
        hashTable.insert(new Person("abc","张三"));
        hashTable.insert(new Person("bcd","李四"));
        hashTable.insert(new Person("bbb","王五"));

        //查找
        Person person = hashTable.find("abc");  //张三
        System.out.println(person.getName());

        person = hashTable.find("bbb"); //王五
        System.out.println(person.getName());

        //风险:  索引数值太大

    }
}

4.压缩可选值

4.1创建JavaBean

public class Person {
    private String key;
    private String name;

    public Person(String key, String name) {
        this.key = key;
        this.name = name;
    }
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

4.2创建HashTable

import java.math.BigInteger;

public class HashTable {
    //数组
    private Person[] arr;

    //构造
    public HashTable() {
        arr = new Person[10];
    }

    public HashTable(int size){
        arr = new Person[size];
    }

    //插入数据
    public void insert(Person person){
        //将关键字key 进行hash化后进行求和再作为索引
        arr[hashCode(person.getKey())] = person;
    }

    //查找数据
    public Person find(String key){
        return arr[hashCode(key)];
    }

    //字符串转化成ASCII码,并且进行幂的连乘,最后取模再返回
    //使用 BigInteger 类型代替int类型
    public int hashCode(String key){
        BigInteger hashCode = new BigInteger("0");
        BigInteger pow = new BigInteger("1");

        for (int i = key.length()-1;i>= 0 ; i--){
            BigInteger value = new BigInteger(String.valueOf(key.charAt(i) - 96));
           hashCode =  hashCode.add(value.multiply(pow));
           pow = pow.multiply(new BigInteger("27"));
        }
        //取模后再转成 int 类型返回
        return hashCode.mod(new BigInteger(String.valueOf(arr.length))).intValue();
    }
}

4.3测试

public class Test {
    public static void main(String[] args) {

        HashTable hashTable = new HashTable();

        //插入数据
        hashTable.insert(new Person("abcdefghijklmn","张三"));
        hashTable.insert(new Person("bcd","李四"));
        hashTable.insert(new Person("ccc","王五"));

        //查找
        Person person = hashTable.find("abcdefghijklmn");  //张三
        System.out.println(person.getName());

        person = hashTable.find("bcd"); //李四
        System.out.println(person.getName());

        //风险:  压缩空间后可能出现重复索引值

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值