数据结构与算法(五)--- 哈希表、树、二叉树的入门

一、递归定义程序调用自身的编程技巧称为递归(recursion)。 递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法, 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解, 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。 递归的能力在于用有限的语句来定义对象的无限集合。 一...
摘要由CSDN通过智能技术生成

一、哈希表

(一)哈希表的定义

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

数组,链表,哈希表的区别:

  • 数组(顺序表):寻址容易,只要使用下标即可;插入和删除难,会有大量的元素进行移动
  • 链表:插入与删除容易,但是查询难
  • 哈希表:寻址容易,插入删除也容易,综合了数组和链表的特性。

(二)哈希表的图解

Key : {14, 19, 5, 7, 21, 1, 13, 0, 18} 散列表: 大小为13 的数组 a[13]; 散列函数: f(x) = x mod 13; 遇到hash冲突则hash值+1(直到加到没有hash冲突的位置,此处先用简单的方式来解决hash冲突)

  • 散列表的大小:是需要根据自己的需求而定的
  • 散列函数:为了key计算后的结果hash值,能够不超出定义的散列表的大小
  • hash冲突:不同的key通过散列函数计算的hash值一样。自定义的哈希表需要设计好hash冲突解决的方法。
  • 装填因子:放入散列表中的数据个数 / 散列表的大小
    [1] 假设装填因子=0.7,散列表中的数据个数 / 散列表的大小 = 9/13 = 0.7,如果散列表中数据个数达到了9个,就需要对散列表进行扩容,扩容后再存放新的数据。HashMap设置的装填因子是0.75。
    [2] 那么为什么不全部放满了再扩容呢,需要根据装填因子?因为数据越接近散列表的大小,产生冲突的可能会越来越大
  • 缺点:扩容需要消耗大量的空间和性能。
    扩容会导致散列函数重新变化,[ 比如扩容后大小为50,那么f(x) = x mod 50 ],原本存入哈希表的key值都需要重新计算。
    HashMap的扩容就是2的n次方计算的。
  • 应用:散列表应用场景,是在数组大小变化的可能性不大的情况下:电话号码,字典,点歌系统,QQ,微信的好友等。
    比如系统的电话号码存放有上限值的,这样增删改查就能保持性能最快的一种方式。

在这里插入图片描述

(三)哈希表的拉链法

要能够手写一套性能优异的哈希表,需要了解所有的树结构。不同的语言,设计的哈希表也是有些差异的,HashMap就是采用了拉链法。

1、JDK1.8以前:数组 + 链表

优点:

  • 查找快:时间复杂度 O(n) ,( O(n/线性表的size) ) ,是一个线性的查找
    [e.g.] f(337) = 1,查找到数组角标1,然后再单链表查询到337。
  • 插入快:查找到数组角标,单链表的插入
  • 删除快:查找到数组角标,单链表的删除


缺点:

  • 大数据时代,如果数组容量不是很大,很有可能出现某一行链表个数超过几万几十万。(解决方法见数组 + 链表 + 红黑树)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值