字典(也被称为映射)和散列表是用来存储唯一值的数据结构。
在字典和散列表中都是用[键,值]的形式存储数据的。其中键名是用来查询特定元素的。
在ECMAScript 6中包含了Map类的实现,也就是字典。在ECMAScript 6中的Map类型是一种存储着许多键值对的有序列表,其中键名和对应的值支持所有的类型。和对象不太一样,不会将键名强制转换为字符串类型。
以ECMAScript 6中的Map类为基础实现一个字典类。
function Dictionaries() {
var items = {};
this.set = function (key, value) {
//向字典中添加新元素
return items[key] = value;
};
this.remove = function (key) {
//通过键值从字典中移除元素
if(this.has(key)) {
delete items[key];
return true;
}
return false;
};
this.has = function (key) {
//判断键值是否存在
return items.hasOwnProperty(key);
};
this.get = function (key) {
//通过键值获取元素
return this.has(key) ? items[key] : undefined;
};
this.clear = function () {
//将字典中所有元素全部删除
items = {};
};
this.size = function () {
//获取字典所包含元素的数量
//有兼容问题
// return Object.keys(items).length;
//通用
var count = 0;
for(var key in items) {
if(items.hasOwnProperty(key)) {
count++;
}
}
return count;
};
this.keys = function () {
//获取字典所包含的所有键值以数组形式返回
//有兼容问题
// return Object.keys(items);
//通用
var keys = [];
for (var key in items) {
if (items.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys;
};
this.values = function () {
//获取字典中所有包含的数值以数组形式返回
var values = [];
for (var key in items) {
if(items.hasOwnProperty(key)) {
values.push(items[key]);
}
}
return values;
};
}
var dictionaries = new Dictionaries();
dictionaries.set('name', 'Jason');
dictionaries.set('age', 23);
dictionaries.set('hobby', 'short story');
console.log(dictionaries.size()); //3
console.log(dictionaries.keys()); //[ 'name', 'age', 'hobby' ]
console.log(dictionaries.values()); //[ 'Jason', 23, 'short story' ]
散列表
HashTable类,也叫HashMap类,是Dictionary类的一种散列表实现方式。
散列算法的作用:是尽可能快的在数据结构中找到一个值。在数组中,通常获得一个值,需要遍历整个数据结构来找到他。如果使用散列函数,就能知道值的具体位置,因此能够快速检索到该值。散列函数的作用是给定一个键值,然后返回值在表中的地址。
创建一个散列表
function HashTable() {
var table = [];
var hashFunction = function (key) {
//散列函数,根据每个字符串的ASCII码值的和得到
// 一个数字做为散列表项的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 = hashFunction(key);
table[position] = value;
};
this.remove = function (key) {
//移除散列表中的某个项
table[hashFunction(key)] = undefined;
};
this.get = function (key) {
//获取散列表中的某个项
return table[hashFunction(key)];
};
}
var hash = new HashTable();
hash.put('Jason', 'jason@email.com');
console.log(hash.get('Jason')); //jason@email.com
处理散列表中的冲突
哈希冲突:每一个键都对应有散列值,当不同的值在散列表中对应相同位置的时候,就会产生冲突。
处理冲突的方法有:
分离链接:为散列表的每一个位置创建一个链表并将元素存储在里面。
线性探查:当想向表中某个位置加入一个新元素时,如果索引为index的位置以及被占据,就尝试index+1的位置,如果也被占据就继续+1,以此类推。
双散列法。