array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 哈希表(Hash table) - 爱码网

//...................哈希表........................

1.什么是哈希表?

哈希表(Hash table,又叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。即,它通过吧关键码值映射到表中的某一个位置来存储元素,然后根据关键码用同样的方式直接访问,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

2.哈希表做法:把Key通过一个固定的算法函数即哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当做数组的下标,将value存储在以该数字为下标的数组空间中。即在关键码和存储位置之间直接建立了映像。

当时用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value.

3.哈希表优点:

*****数组的特点是:寻址容易,插入和删除困难。

       链表的特点是:寻址困难,插入和删除容易。

哈希表结合了二者的优点,做到了寻址容易,插入删除也容易。

4.哈希表的实现方式----拉链法

如图:

哈希表(Hash table)

左边是个数组,数组的每个成员包含一个指针,指向一个链表的头,这个链表可能为空,也可能有很多元素,

我们根据元素的一些特征将元素分配到不同的链表中,也是根据这些特征,找到正确的链表,从链表中找出这个元素。

散列法一:除留余数法

index = value%p;  //对元素取模运算。

其中p不是接近2的幂

上图 index = value%16.

散列法二:平方散列法:

index = (value*value)>>28

注:>>(右移)相当于除以2^28,

       <<(左移)相当于乘以2^28

例如 4>>1  0100(4) -- 0010(2)  相当于4除以2^1,结果为2

        2<<2  0010(2)  ---1000(8) 相当于2乘以2^2,结果为8

综上:右移n位相当于除以2^n,左移n位相当于乘以2^n.

平方散列法适用于数值分配比较均匀的数据。

散列法三--斐波那契散列法

斐波那契数列:0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,……

平方散列法是拿value本身作为乘数,这里我们找一个理想的乘数

1.对于16位整数而言,这个乘数是40503,

2.对于32位整数而言,这个乘数是2654435769

3.对于64位整数而言,这个乘数是11400714819323198485

这几个数字是由黄金分割法则所得来的,描述黄金分割法则的最经典表达式就是斐波那契数列。


例如对于我们常见的32位整数:

index = (value*2654435769)>>28

如图:

哈希表(Hash table)


 5.哈希表的冲突:当关键字值域远大于哈希表的长度,而且事先并不知道关键字的具体取值时,就会发生冲突

                              另外,当关键字的实际取值远大于哈希表的长度,而且表中已装满了记录,此时插入一个新纪录,                               不仅发生冲突,还会发生溢出。

6.处理哈希冲突的方法(溢出处理技术):避免和解决,即冲突避免机制和冲突解决机制

 ---避免哈希冲突的方法是选择合适的哈希函数。

 ---解决哈希冲突的方法:

1.开放寻址法(Open Addressing):

将所有的元素都存放在哈希表数组中,不使用额外的数据结构。

开放寻址法最简单的一种实现就是线性探查法,步骤如下:

  ~当插入新的元素时,使用哈希函数在哈希表中定位元素位置。

  ~检查哈希表中该位置是否已经存在元素,如果该位置内容为空,则插入并返回,否则,转向步骤3.

  ~如果该位置为i,则检查i+1是否为空,如果已被占用,则检查i+2,依次类推,直到找到一个内容为空的位置并插入。


例子如下:

给出一组数据,它们的关键码是37,25,14,36,49,68,57,11,散列表为hash[12];

表的大小为m = 12,采用的散列函数 Hash(x) = x%11;   其中11是小于等于m最接近m的质数。

采用线性探查法得到关键码在散列表中散列位置如下:

线性探查法处理冲突
0 1 2 3 4 5 6 7 8 9 10 11
11   68 25 37 14 36 49 57      
线性探查的方式虽然简单,但并不是解决冲突最好的策略,因为会导致同类哈希的聚集。即不同探查序列的关键码占据了可利用的空桶,使得为寻找某一个关键码需要经历不同的探查序列的元素。导致搜索时间增加。

为此,可采用二次探查法,改善上述的“聚集”问题,减少为完成搜索所需的平均探查次数。

2.二次探查法:即每次检查位置空间的步长为平方倍数。

步骤为:

  ~当插入新的元素时,使用哈希函数在哈希表中定位元素位置。

  ~检查哈希表中该位置是否已经存在元素,如果该位置内容为空,则插入并返回,否则,转向步骤3.

  ~如果该位置为i,则检查i+1^2是否为空,如果已被占用,则检查i-1^2,,i+2^2,i-2^2,依次类推,直到找到一个内容为空的位置并插入。

注:表的大小应该是一个值为4k+3的质数,其中k是一个整数。


例子:给出一组元素,它们的关键码为37,25,14,36,49,68,57,11.因为散列表的大小必须是满足4k+3的质数,可取m = 19,这样散列表可设定为HT[19],采用的散列函数:

Hash(x) = x%19;

采用二次探查法处理冲突得到关键码在散列表中散列位置如下:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
57           25       11 49 68   14     36 37

3.双散列法:使用双散列法时,需要两个散列函数。第一个散列函数Hash()按元素的关键码key计算元素所在的位置,一旦发生冲突,就利用第二个散列函数ReHash()计算该元素到达下一个未知的移位量。它的取值与key的取值有关,要求它的取值应该小于地址空间大小(m)且与m互质的正整数。

即:第一个散列函数为Hash(x) = x%m; 

  第二个散列函数为Hash(j) = (j+p)%m; 其中p是小于m且与m互质的整数。

利用双散列法,按一定的距离,跳跃式的寻找下一个位置,减少了“堆积”的机会。


解决哈希冲突的方法:

1.链地址法:首先对关键码集合用某散列函数计算它们的存储位置。若设散列表地址空间的所有位置0~m-1,则关键码集合中的所有关键码被划分为m个子集合,通过散列函数计算出来的具有相同地址的关键码归于同一子集合。

将散列到同一个地址的所有关键码都放到一个链表中。

通俗一点讲就是将哈希表中每个位置都映射到了一个链表。当冲突发生时,冲突的元素将被添加到同列表中,而每个同都包含了一个链表以存储相同哈希的元素。

例如:

现在如果我们要将五个员工的信息插入到哈希表中:

  • Alice (333-33-1234)
  • Bob (444-44-1234)
  • Cal (555-55-1237)
  • Danny (000-00-1235)
  • Edward (111-00-1235)
哈希表(Hash table)

上图中的哈希表包含了8个桶,也就是黄色背景的位置,如果一个新的元素要添加至哈希表中,将被添加至key的哈希所对应的桶中,如果在相同位置已经有元素存在,则将新元素添加到列表的前面。

使用链接技术添加元素的操作涉及到哈希计算和链表操作,但其仍为常量,渐进时间为 O(1)。而进行查询和删除操作时,其平均时间取决于元素的数量和桶(bucket)的数量。具体的说就是运行时间为 O(n/m),这里 n 为元素的总数量,m 是桶的数量。但通常对哈希表的实现几乎总是使 n = O(m),也就是说,元素的总数绝不会超过桶的总数,所以 O(n/m) 也变成了常量 O(1)。


//..........................................全域哈希

全域哈希法是指:随机的选择哈希函数,使之独立于要存储的元素,这种方法称作全域哈希。

全域哈希目的是为了改进在向哈希表中插入元素时,如果所有的元素全部被哈希到一个桶中,此时数据的存储实际上就是一个链表,那么平均的查找事件为O(n),为了改进,我们采取全域哈希法。

基本思想:在执行开始时,从一组哈希函数中,随机的抽取一个要使用的哈希函数,就像在快速排序一样,随机化保证了没有哪一种输入会始终导致最坏情况的发生。同时,随机化也使得即使是对同一个输入,算法在每一次的执行时的情况也都不一样。这样就确保了对于任何输入,算法都具有较好的平均运行情况。










相关文章: