PHP有数据的一个非常重要的一类,就是关联数组。又称为哈希表(hash table),是一种很好用的数据结构。



在程序中。我们可能会遇到须要消重的问题,举一个最简单的模型:



有一份username列表。存储了 10000 个username,没有反复项;

另一份黑名单列表,存储了 2000 个username,格式与username列表同样。

如今须要从username列表中删除处在黑名单里的username,要求用尽量快的时间处理。



这个问题是一个小规模的处理量,假设实际一点,2 个表都可能非常大,比方有 2 亿条记录。

我最開始想到的方法,就是做一个嵌套的循环。设username表有 M 条记录,黑名单列表有 N 条记录,那么,循环的次数是 M * N 次。

PHP 版代码:

01 <?php  

02 foreach($arrayM as $keyM => $nameM) {  

03 foreach($arrayN as $nameN) {  

04 if ($nameM == $nameN) {  

05 // 本行运行了 M * N 次!  

06 unset($arrayM[$keyM]);  

07 }  

08 }  

09 }  

10 return $arrayM;  

11 ?

>

还有一种方式,利用数组索引。



PHP 是一种弱类型的语言,不像 C 语言那样有严格的变量类型限制。C 语言的数组。每个元素的类型必须一致。并且索引都是从
0 開始。

PHP 的数组,能够用字符串作为索引,也称为关联数组。

数组索引,有一个天然的限制就是不会反复。并且訪问的时候不须要查找,能够直接定位。

还是刚才的那个问题,我们採用还有一种办法。



把黑名单列表的username组织到一个数组里,数组的索引就是username。



然后,遍历用户列表的时候,仅仅需直接用 isset 查询那个username是否存在就可以。



PHP 版代码:

01 <?php  

02 $arrayHash = array();  

03 foreach($arrayN as $nameN) {  

04 // 本行运行了 N 次。  

05 $arrayHash[$nameN] = 1;  

06 }  

07  

08 foreach($arrayM as $keyM => $nameM) {  

09 if (isset($arrayHash[$nameM])) {  

10 // 本行运行了 M 次!

11 unset($arrayM[$keyM]);  

12 }  

13 }  

14 return $arrayM;  

15 ?

>

能够看到,优化过的代码,循环次数是 M + N 次。



假如 M 和 N 都是 10000,优化前,循环了 1 亿次;优化后。仅仅循环了 20000 次。差了 5000 倍。

假设第二个程序耗时 1 秒。则第一个程序须要将近一个半小时!

=========================================================================

hash一个貌似比較复杂的东西,实际上理解起来并不那么夸张。这里做个笔记。



hash,中文翻译成杂乱的东西。有人也叫它杂凑,或者翻译成什么都不是的音译“哈希”。



简单说来。hash就是为了把一个复杂的字串,通过一定的转换,得到一个简单的数字(一般是数字)。

如"abcd" 用各个字符的值直接相加。再取对10的余数,既(a+b+c+d)。来得到一个数字。例如说结果为5,那么这个5就能在一定意义上代表这个字串 abcd了。或者说这个5也能够说是这个字串的一个标记性的东西,并且是简化了的标记,所以又有人叫这个5为字串的摘要,或指纹。

这个5,有一个好的用处就是能够作为一个数组的下标来用,如我自己构造一个指针数组void* hash_array[10]。那么我就能够把5那个位置上填上一个指针,如指向abcd字串。

这种话。我假设要去查询一个字串是否存在,就不须要对一个数组使用字符串循环对照这种慢操作,而直接先得到某个字串的hash值,再用这个hash值,在数组下标里直接找。这样速度要快上非常多,特别是数据比較多的时候。



能够看到上面计算hash值时,出来的结果,可能并非从0開始的,如我们算出的就是5。也就是说,这个5是在数组中的某个不确定的位置,或者能够叫做是一个杂凑出来的位置。其它位置可能一直就空着在。这就是这个数组或表格叫hash表的原因了。

但有个问题,上面的转换方法,直接相加,再取个余数,在字符串变为abdc时。结果得到的还是数字5。

这个就是上面这个算法的一个问题了。即它不能保证一个唯一性。所以就出现了非常多hash算法的研究,如MD4,MD5,SHA-1等,来保证唯一性。

但上面这个算法还是能够使用的,做法就是在abdc经过hash得到5后,去检查5是否被占用。假设占用了,那么就把数字加1。即为6,假设6没被占用,就填上值。假设后面某个字串算出一个值是6,但6已经被占用了,那么就再加1。再存。

取数据的时候,能够先算出hash值后,再看里面的内容是不是你想要的,假设不是,就加1去看,最后得到一个。



所以这里hash表的内容并非象一般的数组最開始就组织好了的,而是兴许慢慢往里添加的。

hash表里存的内容一般能够是一个指针,这个指针能够指向一个大的结构也是能够的。这个结构里能够有key, value信息。

hash表也能够不是数组,你能够把它组织成一个链表,链表里的node的结构中能够有一个參数就是那个数字的hash_value。用来高速查找用。

尽管在非常多时候hash被用在加密等场合,但在一般的应用程序代码中,也能够用它来存简单的数据存储,代码的这样的高效率将是非常。

版权声明:本文博主原创文章,博客,未经同意不得转载。

PHP关联数组和哈希表(hash table) 未指定的更多相关文章

  1. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

  2. 词典(二) 哈希表(Hash table)

    散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...

  3. 什么叫哈希表(Hash Table)

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

  4. 数据结构 哈希表(Hash Table)_哈希概述

    哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...

  5. 哈希表(Hash table)

  6. Perl 引用:引用就是指针,Perl 引用是一个标量类型可以指向变量、数组、哈希表(也叫关联数组)甚至子程序。

    Perl 引用引用就是指针,Perl 引用是一个标量类型可以指向变量.数组.哈希表(也叫关联数组)甚至子程序,可以应用在程序的任何地方. 1.创建引用1.使用斜线\定义变量的时候,在变量名前面加个\, ...

  7. Redis原理再学习04:数据结构-哈希表hash表(dict字典)

    哈希函数简介 哈希函数(hash function),又叫散列函数,哈希算法.散列函数把数据"压缩"成摘要,有的也叫"指纹",它使数据量变小且数据格式大小也固定 ...

  8. Swift4 基本数据类型(范围型, Stride型, 数组, 字符串, 哈希表)

    创建: 2018/02/28 完成: 2018/03/04 更新: 2018/05/03 给主要标题加上英语, 方便页内搜索 [任务表]TODO 范围型(Range)与Stride型  与范围运算符相 ...

  9. 哈希表(Hash)的应用

    $hs=@() #定义数组 $hs=@{} #定义Hash表,使用哈希表的键可以直接访问对应的值,如 $hs["王五"] 或者 $hs.王五 的值为 75 $hs=@''@ #定义 ...

随机推荐

  1. 谨记给UpdatePanel中动态添加的控件赋ID

    原文:谨记给UpdatePanel中动态添加的控件赋ID 昨天下定决 心对上次做的布局编辑器控件加以改进,其中最主要变化的就是要完全使用ASP.NET AJAX!但是很遗憾,虽然耳闻已久,但目前对AS ...

  2. pro-engineer&UG

    Pro/Engineer操作软件是美国参数技术公司(PTC)旗下的CAD/CAM/CAE一体化的三维软件.Pro/Engineer软件以参数化著称,是参数化技术的最早应用者,在目前的三维造型软件领域中 ...

  3. linux下登陆mysql失败

    一.提示由于没有密码,拒绝登陆 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) 1 ...

  4. Hot Days Codeforces Round #132 (Div. 2) D(贪婪)

    Description The official capital and the cultural capital of Berland are connected by a single road ...

  5. Cocos2d-x3.0下一个 Lua与C++打电话给对方

    这里谈下Lua与C++如何实现相互通话 原来的连接:http://blog.csdn.net/qqmcy/article/details/26052771 DJLCData.h 实现类 // // D ...

  6. ACM/ICPM2014鞍山现场赛D Galaxy (HDU 5073)

    题目链接:pid=5073">http://acm.hdu.edu.cn/showproblem.php?pid=5073 题意:给定一条线上的点,然后能够去掉当中的m个,使剩下的到重 ...

  7. 金色的 SQL注意事项(1)

    page(1-75) 最好是没有意义的主键字段,以方便未来的扩展. PS:主键,以后标书编码填错须要改的时候,关联表都须要跟着改.假设是一个无意义的自增字段是主键就无此原因. 主键最好不要设置为联合主 ...

  8. PHP socket类

    没事的时候自己封装了一个socket类 功能非常easy和curl功能是一样的 class socketClass{ private $host; private $url; private $err ...

  9. windows phone 独立存储空间的操作 (2)

    原文:windows phone 独立存储空间的操作 (2) IsolatedStorage独立存储空间是保存应用程序的一些数据已经配置文件,独立存储空间相对于其他的wp程序是独立的,也就是说每个wp ...

  10. OGG-01008 Extract displays Discarding bad record (discard recs=1) when using filter or where clause

    因为在extract參数文件里使用了where语句,而where后面的的条件列又不是主键,没有为update.delete操作记录日志,因此会报1008错误. Applies to: Oracle G ...