js数据结构和算法(五)字典和散列(hash)

2024-04-24 06:38

本文主要是介绍js数据结构和算法(五)字典和散列(hash),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是字典结构?

字典是以键值对形式存储数据的数据结构,就像电话号码薄里的名字和电话号码那样的一一对应的关系。

javascriptObject类就是以这样的一种字典形式设计的。

键值对在字典中以这样的方式标记:d = {key1 : value1, key2 : value2 }。字典中的键/值对是没有顺序的。如果你想要一个特定的顺序,那么你应该在使用前自己对它们排序。

Dictionary类

Dictionary类的基础是Array类,而不是Object类。我们想对字典中的键排序,而在js中是不能对 对象 的属性进行排序的。话虽如此,但在js中一切皆对象,数组也是对象。以下面的代码开始定义Dictionary类:

<script type="text/javascript">function Dictionary(){this.datastore = new Array();}
</script>

先来定义add()方法。该方法接受两个参数:键和值。键是值在字典中的索引,代码如下:

function add(key,value){this.datastore[key] = value;
}

接下来定义find()方法,该方法以  做为参数,返回和其关联的值。代码如下:

function find(key){return this.datastore[key];}

从字典中删除键-值对 需要使用js中的delete函数。该函数是Object类的一部分,该函数同时删掉键和与其关联的值:

function remove(key){delete  this.datastore[key];}

最后,我们希望可以显示字典中所有的键-值对,可以使用如下的方法:

function showAll(){for(var key in Object.keys(this.datastore)){print(key + "->" + this.datastore[key]);}}

Dictionary类的辅助方法

我们可以定义一些在特定情况下有用的辅助方法。比如要知道字典中的元素个数可以定义一个count()方法,代码如下:

function count(){var n=0;for(var key in Object.keys(this.datastore)){++n;}return n;}

为什么不使用length属性?这是因为当键的类型为字符串时,length属性就不管用了

还可以定义一个clear清除方法:

function clear(){for each(var key in Object.keys(this.datastore)){delete  this.datastore[key];}}

备注:

for each in(IE6,7,8不支持)无法获得对象的属性名,只能获取到属性值。
另外,遍历对象也尽量使用for in 而不是for each,而遍历数组的话还是使用for循环吧

for each in无法获得对象的属性名,只能获取到属性值。

散列(hash)

什么是哈希表?

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

  哈希表的做法其实很简单,就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。

  而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位

散列表的查找步骤

当存储记录时,通过散列函数计算出记录的散列地址当查找记录时,我们通过同样的是散列函数计算记录的散列地址,并按此散列地址访问该记录

js中,散列函数会将每个键值映射为一个唯一的数组索引。然而,键的数量是无限的,数组的长度是有限的,所以,应该让散列函数尽量将键均匀地映射到数组中。

哈希表也是种数据结构,它可以提供快速的插入操作和查找操作。哈希表运算速度极快,哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。哈希表不仅速度快,编程实现也相对容易。

哈希表算法

哈希表最常见的例子是以学生学号为关键字的成绩表,1号学生的记录位置在第一条,10号学生的记录位置在第10条...

如果我们以学生姓名为关键字,如何建立查找表,使得根据姓名可以直接找到相应记录呢?

用上述得到的数值作为对应记录在表中的位置,得到下表:
 上面这张表即哈希表。

如果将来要查李秋梅的成绩,可以用上述方法求出该记录所在位置:

李秋梅:lqm 12+17+13=42 取表中第42条记录即可。

HashTable类

我们使用一个类来表示散列表,该类包含计算散列值的方法、向散列中插入数据的方法、从散列表中读取数据的方法、显示散列表中数据分布的方法等。
HashTable类的构造函数定义如下:

function HashTable(){this.table = new Array(137);//设定数组长度为137,质数this.simpleHash = simpleHash;this.showDistro = showDistro;this.put = put;}

散列函数的选择依赖于键值的数据类型。如果键是整形,最简单的散列函数就是以数组的长度对键取余。

使用一个简单的散列函数做散列:

   load("HashTable.js");var someNames = ['David','Jennifer','Donnie','Raymond','Cynthia','Mike','Clayton','Danny','Jonathan'];var hTable = new HashTable();for(var i = 0;i < someNames.length;i++){hTable.put(someNames[i]);}hTable.showDistro();

输出如下:

35:Cynthia
45:Clayton
57:Donnie
77:David
95:Danny
116:Mike
132:Jennifer
134:Jonathan

simpleHash()函数通过使用jscharCodeAt()函数,返回每个字符的ASCII码值,然后再将它们相加得到散列值。put方法通过调用simpleHash()函数得到数组的索引,然后将数据存储到该索引对应的位置上。

一个更好的散列函数

为了避免碰撞,首先要确保散列表中用来存储数据的数组其大小是个质数,这和计算散列值时使用的取余运算有关。数组的长度应该在100以上,这是为了让数据在散列表中分布得更均匀

散列化整型键

这里我们使用一个展示学生成绩的数据集,将随机产生一个9位数的键,用以识别学生身份和一门成绩,下面是产生学生数据(包含ID和成绩)的函数:

function getRandomInt(min,max){return Math.floor(Math.random()*(max-min+1))+min;
}
function genStuData(arr){for(var i = 0;i<arr.length;++i){var num = '';for(var j = 1;j<=9;++j){num += Math.floor(Math.random()*10);}num += getRandomInt(50,100);arr[i] = num;}
}

使用getRandomInt()函数时,可以指定随机数的最值。genStuData()函数生成学生的数据。里层的循环用来生成学生的ID,紧跟在循环后面的代码生成一个随机的成绩,并把成绩弄在ID的后面。主程序会把ID和成绩分离。散列函数将学生ID里的数字相加,使用simpleHash()函数计算出散列值。

对散列表排序

put方法同时接受键和数据作为参数,对键值散列后,将数据存储到散列表中:

function put(key,data){var pos = this.betterHash(key);this.table[pos] = data;
}

put方法将键值散列化后,将数据存储到散列化后的键值对应在数组中的位置上。

从散列表中取值

定义get()方法,用以读取存储在散列表中的数据。该方法同样需要对键值进行散列化,然后才能知道数据存储在数组的什么位置,代码如下:

function get(key){return this.table[this.betterHash(key)];
}

这篇关于js数据结构和算法(五)字典和散列(hash)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/931022

相关文章

python 字典d[k]中key不存在的解决方案

《python字典d[k]中key不存在的解决方案》本文主要介绍了在Python中处理字典键不存在时获取默认值的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录defaultdict:处理找不到的键的一个选择特殊方法__missing__有时候为了方便起见,

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm