集合、字典和散列表可以存储不重复的值。在集合中,我们感兴趣的是每个值本身,并把它当作主要元素。在字典中,我们用[键,值]的形式来存储数据。在散列表中也是一样(也是以[键,值]对的形式来存储数据)。但是两种数据结构的实现方式略有不同,本文将详细介绍字典和散列表这两种数据结构
转载于https://www.cnblogs.com/xiaohuochai/p/8183020.html
字典
集合表示一组互不相同的元素(不重复的元素)。在字典中,存储的是[键,值]对,其中键名是用来查询特定元素的。字典和集合很相似,集合以[值,值]的形式存储元素,字典则是以[键,值]的形式来存储元素。字典也称作映射
【创建字典】
与Set类相似,ECMAScript 6同样包含了一个Map类的实现,即我们所说的字典
下面将要实现的类就是以ECMAScript 6中Map类的实现为基础的。它和Set类很相似(但不同于存储[值,值]对的形式,我们将要存储的是[键,值]对)
这是我们的Dictionary类的骨架:
function Dictionary() {
var items = {};
}
与Set类类似,我们将在一个Object的实例而不是数组中存储元素。 然后,我们需要声明一些映射/字典所能使用的方法
set(key,value):向字典中添加新元素。 remove(key):通过使用键值来从字典中移除键值对应的数据值。 has(key):如果某个键值存在于这个字典中,则返回true,反之则返回false。 get(key):通过键值查找特定的数值并返回。 clear():将这个字典中的所有元素全部删除。 size():返回字典所包含元素的数量。与数组的length属性类似。 keys():将字典所包含的所有键名以数组形式返回。 values():将字典所包含的所有数值以数组形式返回。
【has】
首先来实现has(key)方法。之所以要先实现这个方法,是因为它会被set和remove等其他方法调用。这个方法的实现和之前在Set类中的实现是一样的。使用JavaScript中的in操作符来验证一个key是否是items对象的一个属性。可以通过如下代码来实现:
this.has = function(key) {
return key in items;
}
【set】
该方法接受一个key和一个value作为参数。我们直接将value设为items对象的key属性的值。它可以用来给字典添加一个新的值,或者用来更新一个已有的值
this.set = function(key, value) {
items[key] = value; //{1}
}
【remove】
它和Set类中的remove方法很相似,唯一的不同点在于我们将先搜索key(而不是value),然后我们可以使用JavaScript的delete操作符来从items对象中移除key属性
this.remove = function(key) {
if (this.has(key)) {
delete items[key];
return true;
}
return false;
}
【get】
get方法首先会验证我们想要检索的值是否存在(通过查找key值),如果存在,将返回该值, 反之将返回一个undefined值
this.get = function(key) {
return this.has(key) ? items[key] : undefined;
};
【values】
首先,我们遍历items对象的所有属性值(行{1})。为了确定值存在,我们使用has函数来验证key确实存在,然后将它的值加入values数组(行{2})。最后,我们就能返回所有找到的值。这个方法以数组的形式返回字典中所有values实例的值:
this.values = function() {
var values = {};
for (var k in items) { //{1}
if (this.has(k)) {
values.push(items[k]); //{2}
}
}
return values;
};
【clear】
this.clear = function(){
items = {};
};
【size】
this.size = function(){
return Object.keys(items).length;
};
【keys】
keys方法返回在Dictionary类中所有用于标识值的键名。要取出一个JavaScript对象中所有的键名,可以把这个对象作为参数传入Object类的keys方法,如下:
this.keys = function() {
return Object.keys(items);
};
【items】
下面来验证items属性的输出值。我们可以实现一个返回items变量的方法,叫作getItems:
this.getItems = function() {
return items;
}
【完整代码】
Dictionary类的完整代码如下所示
function Dictionary(){
var items = {};
this.set = function(key, value){
items[key] = value; //{1}
};
this.delete = function(key){
if (this.has(key)){
delete items[key];
return true;
}
return false;
};
this.has = function(key){
return items.hasOwnProperty(key);
//return value in items;
};
this.get = function(key) {
return this.has(key) ? items[key] : undefined;
};
this.clear = function(){
items = {};
};
this.size = function(){
return Object.keys(items).length;
};
this.keys = function(){
return Object.keys(items);
};
this.values = function(){
var values = [];
for (var k in items) {
if (this.has(k)) {
values.push(items[k]);
}
}
return values;
};
this.each = function(fn) {
for (var k in items) {
if (this.has(k)) {
fn(k, items[k]);
}
}
};
this.getItems = function(){
return items;
}
}
散列表
下面将详细介绍HashTable类,也叫HashMap类,是Dictionary类的一种散列表实现方式
散列算法的作用是尽可能快地在数据结构中找到一个值。如果要在数据结构中获得一个值(使用get方法),需要遍历整个数据结构来找到它。如果使用散列函数,就知道值的具体位置,因此能够快速检索到该值。散列函数的作用是给定一个键值,然后返回值在表中的地址
举个例子,我们继续使用在前面使用的电子邮件地址簿。我们将要使用最常见的散列函数——“lose lose”散列函数,方法是简单地将每个键值中的每个字母的ASCII值相加
function HashTable() {
var table = [];
var Valuepair = function(key, value) {
this.key = key;
this.value = value;
this.toString = function() {
return '[' + this.key + '-' + this.value + ']';
}
};
var loseloseHashCode = function(key) {
var hash = 0;
for (var i = 0; i < key.length; i++) {
hash += key.charCodeAt(i);
}
return hash % 37;
};
// 替代loselose的方法
var djb2HashCode = function(key){
var hash = 5381;
for (var i = 0; i < key.length; i++) {
hash = hash * 33 + key.charCodeAt(i);
}
return hash % 1013;
}
// 分离连接
this.put = function(key, value) {
var position = loseloseHashCode(key);
if (table[position] == undefined) {
table[position] = new LinkList();
}
table[position].append(new Valuepair(key,value));
};
this.get = function(key){
var position = loseloseHashCode(key);
if (table[position] !== undefined) {
var currrent = table[position].getHead();
while(currrent.next) {
if (currrent.element.key === key) {
return currrent.element.value;
}
currrent = currrent.next;
}
if (current.element.key === key) {
return currrent.element.value;
}
}
return undefined;
};
this.remove = function(key){
var position = loseloseHashCode(key);
if (table[position] !== undefined) {
var currrent = table[position].getHead();
while(currrent.next){
if (currrent.element.key === key) {
table[position].remove(currrent.element);
if (table[position].isEmpty()) {
table[position] = undefined;
}
return true;
}
currrent = currrent.next;
}
if (currrent.element.key === key) {
table[position].remove(currrent.element);
if (table[position].isEmpty()) {
table[position] = undefined;
}
return true;
}
}
return false;
};
}
// 线性探查
function HashTable() {
var table = [];
var Valuepair = function(key, value) {
this.key = key;
this.value = value;
this.toString = function() {
return '[' + this.key + '-' + this.value + ']';
}
};
var loseloseHashCode = function(key) {
var hash = 0;
for (var i = 0; i < key.length; i++) {
hash += key.charCodeAt(i);
}
return hash % 37;
};
this.put = function(key, value) {
var position = loseloseHashCode(key);
if (table[position] == undefined) {
table[position] = new Valuepair(key, value);
} else {
var index = ++position;
while(table[index] != undefined) {
index++;
}
table[index] = new Valuepair(key, value);
}
};
this.get = function(key) {
var position = loseloseHashCode(key);
if (table[position] !== undefined) {
if (table[position].key === key) {
return table[position].value;
} else {
var index = ++position;
while(table[index] === undefined || table[index].key !== key) {
index++;
}
if (table[position].key === key) {
return table[index].value;
}
}
}
return undefined;
};
this.remove = function(key) {
var position = loseloseHashCode(key);
if (table[position] !== undefined) {
if (table[position].key === key) {
table[position] = undefined;
} else {
var index = ++position;
while(table[index] === undefined || table[index].key !== key) {
index++;
}
if (table[position].key === key) {
table[index] = undefined;
}
}
}
return undefined;
};
}