数据结构学习之哈希表篇(一)

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

哈希表充分体现了算法设计领域的经典思想:用空间换时间。
哈希表是时间与空间之间的平衡。
哈希函数的设计也是很重要的。
“键”通过哈希函数得倒的“索引”分布越均匀越好。

我们关注的“键"的类型,在转化为数组的索引时一般哈希函数的设计原则

整型
小范围正整数直接使用
小范围负整数进行偏移( -100~100—>0~200)
大整数的通常做法:取模,取模时要具体问题具体分析。一个简单的解决办法就是模一个素数(素数又称质数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数)。一个很小的例子来说明为什么要模一个素数,而不是合数:
取余合数4:

10%42
20%40
30%42
40%40
50%42

取余素数7:

10%73
20%76
30%72
40%75
50%71

取模素数时”索引“更连续,哈希冲突更少。

浮点型
在计算机中,浮点型都是32位(float)或者64位(double)的二进制表示,被计算机解析成了浮点数。所以浮点数可以转成整型来处理。

字符串
转成整型处理
166 = 1 * 10 ^ 2 + 6 * 10 ^ 1 + 6 * 10 ^ 0
code = c * B ^ 3 + o * B ^ 2 + d * B ^ 1 + e * B ^ 0
hash(code) = (c * B ^ 3 + o * B ^ 2 + d * B ^ 1 + e * B ^ 0 ) % M
hash(code) = ((((c * B) + o) * B + d) * B + e ) % M
hash(code) = ((((c % M) * B + o) % M * B + d) % M * B + e ) % M
最后一个式子转换为代码:

int hash = 0;
for(int i = 0; i < str.length(); i ++){
    hash = (hash * B + str.charAt(i)) % M
}

复合类型
依然可以转为整型类型。即像处理字符串一样把复合类型的每一部分分开来处理。

当然,转成整型处理,并不是唯一的方法,只是一般的通用方法。
但不管怎样,在设计哈希函数时我们要遵循下面三个原则:

  1. 一致性:即a==b,则hash(a) == hash(b)
  2. 高效性:计算高效简便
  3. 均匀性:哈希值均匀分布

定义一个Student并重写它的hashCode与equals方法:

/**
 * @author ymn
 * @version 1.0
 * @date 2020\6\5 0005 16:00
 */
public class Student {

    int grade;
    int cls;
    String firstName;
    String lastName;

    public Student(int grade, int cls, String firstName, String lastName) {
        this.grade = grade;
        this.cls = cls;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public int hashCode() {
        int B = 7;
        int hash =0;
        hash = hash * B + grade;
        hash = hash * B + cls;
        hash = hash * B + firstName.toLowerCase().hashCode();
        hash = hash * B + lastName.toLowerCase().hashCode();
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        //判断当前对象与obj的引用是否相同
        if (this == obj){
            return true;
        }
        //o是否为空
        if (obj == null){
            return false;
        }
        //是否是一个类,避免出现传进来的类是Student子类的情况
        if (getClass() != obj.getClass()){
            return false;
        }
        Student another = (Student)obj;
        return this.cls == another.cls &&
               this.grade == another.grade &&
               this.firstName.toLowerCase().equals(another.firstName.toLowerCase()) &&
               this.lastName.toLowerCase().equals(another.lastName.toLowerCase());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机数据结构是计算机科学中非常重要的一个概念,它对于程序员和软件开发人员来说至关重要。学习计算机数据结构可以帮助我们更好地理解和处理数据,提高程序的效率和性能。下面是一个关于计算机数据结构学习的任务建议: 1. 学习基础知识:首先,你需要了解计算机数据结构的基本概念和术语。例如,了解数组、链表、栈、队列和树等常见的数据结构及其特点。 2. 学习算法:数据结构和算法密切相关,学习数据结构的同时也要学习与之对应的常用算法。例如,学习排序算法(如冒泡排序、快速排序)、查找算法(如二分查找)等。 3. 实践编程:理论知识只有通过实践才能真正掌握。尝试用编程语言实现各种数据结构和算法,编写相关的代码并进行调试和测试。 4. 解决问题:挑战自己解决一些与数据结构相关的问题。可以参与在线编程竞赛、解决实际应用中的问题或者尝试解答一些经典的算法问题。 5. 深入学习高级数据结构:一旦掌握了基本的数据结构,可以进一步学习一些高级的数据结构,如图、堆、哈希表等。这些数据结构在实际应用中有着广泛的应用。 6. 阅读相关书籍和教程:除了自学,还可以通过阅读经典的计算机科学书籍和在线教程来加深对数据结构的理解和应用。 7. 参与开源项目:参与开源项目是一个很好的锻炼机会,可以与其他开发者一起合作,共同学习和改进数据结构和算法的实现。 8. 持续学习和实践:数据结构是一个广阔而深奥的领域,持续学习和实践是非常重要的。参与讨论、阅读最新的研究论文和技术博客,保持对新技术和新思想的敏感度。 总之,学习计算机数据结构需要坚持不懈的学习和实践。通过理论知识的掌握和实际应用的经验积累,你将能够更好地应用数据结构来解决实际问题,提高程序的效率和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值