您的位置:首页 > 理论基础 > 数据结构算法

JavaScript数据结构——集合、字典和散列表

2016-03-19 22:34 405 查看
集合、字典和散列表都可以存储不重复的值。
在集合中,我们感兴趣的是每个值本身,并把它当作主要元素。在字典和散列表中,我们用 [键,值] 的形式来存储数据。
集合(Set 类):[值,值]对,是一组由无序且唯一(即不能重复)的项组成的。
字典(Map 类):[键,值]对,也称作映射,其中键名是用来查询特定元素的。
散列(HashTable类/HashMap 类):[键,值]对,是Dictionary类的一种散列表实现方式。散列函数的作用是给定一个键值,然后返回值在表中的地址。散列算法的作用是尽可能快地在数据结构中找到一个值。
在一些编程语言中,还有一种叫作散列集合的实现。散列集合由一个集合构成,但是插入、移除或获取元素时,使用的是散列函数。实现散列集合的不同之处在于,不再添加键值对,而是只插入值而没有键。和集合相似,散列集合只存储唯一的不重复的值。
--------------------------------------------------------------------------
(1)集合方法声明:
首先,使用对象来表示集合。

序号
方法
说明
1
add(value)向集合添加一个新的项
2
remove(value)从集合移除一个值
3
has(value)
如果值在结合中,返回 true,否则返回 false
4
clear ( )
移除集合中的所有项
5
size ( )
返回集合所包含元素的数量。与数组的 length 属性类似。
6
values ( )
返回一个包含集合中所有值的数组。
集合的实现:

function HashTable() {
var table = [];

// 散列函数,是HashTable中的一个私有方法
var loseloseHashCode = function(key) {
var hash = 0;
for (var i=0; i<key.length; i++) {
hash += key.charCodeAt(i);    // 给定一个key参数,我们就能根据组成key的每个字符的ASCII码值的和得到一个数字
}
return hash % 37;    // 为了得到比较小的数值,我们会使用hash值和一个任意数做除法的余数
};

// 更好的散列函数(这并不是最好的散列函数,但这是最被社区推荐的散列函数之一)
var djb2HashCode = function(key) {
var hash = 5381;    // 初始化赋值为一个质数,大多数实现都使用5318
for (var i=0; i<key.length; i++) {
hash += hash * 33 + key.charCodeAt(i);    // 将hash与33相乘,当作一个魔力数
}
return hash % 1013;    // 将相加的和与另一个随机质数相除
}

this.put = function(key, value) {
var position = loseloseHashCode(key);    // 给定一个键值,我们需要根据所创建的散列函数计算出它在表中的位置
table[position] = value;    // 将value参数添加到用散列函数计算出的对应的位置上
};

this.get = function(key) {
return table[loseloseHashCode(key)];    //loseloseHashCode(key)会返回值的位置
};

this.remove = function(key) {
table[loseloseHashCode(key)] = undefined;
};

/*解决冲突方法一:分离链接*/

// 为了实现一个使用了分离链接的HashTable实例,我们需要一个新的辅助类来表示将要加入LinkedList实例的元素
var ValuePair = function(key, value) {
this.key = key;
this.value = value;
}

// 分离链接:重写put方法
this.put = function(key, value) {
var position = loseloseHashCode(key);
// 如果这个位置是第一次被加入元素,我们会在这个位置上初始化一个LinkedList类的实例
if (table[position] == undefined) {
table[position] = new LinkedList();
}
table[position].append(new ValuePair(key, value));
}

// 分离链接:重写get方法
this.get = function(key) {
var position = loseloseHashCode(key);

if (table[position] !== undefined) {

//遍历链表来寻找键/值
var current = table[position].getHead();

while (current.next) {
if (current.element.key === key) {
return current.element.value;
}
current = current.next;
}

// 检查元素在链表第一个或最后一个节点的情况
if (current.element.key === key) {
return current.element.value;
}
}
return undefined;
}

// 分离链接:重写remove方法
this.remove = function(key) {
var position = loseloseHashCode(key);

if (table[position] !== undefined) {

var current = table[position].getHead();
while (current.next) {
if (current.element.key === key) {
table[position].remove(current.element);
if (table[position].isEmpty()) {
table[position] = undefined;
}
return true;
}
current = current.next;
}

// 检查是否为第一个或最后一个元素
if (current.element.key === key) {
table[position].remove(current.element);
if (table[position].isEmpty()) {
table[position] = undefined;
}
return true;    // 返回true表示这个元素已经被移除
}
}

return false;    // 返回false表示这个元素在散列表中不存在
}

/*解决冲突方法二:线性探查*/
var ValuePair = function(key, value) {
this.key = key;
this.value = value;
}

// 线性探查:重写put方法
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);
}
}

// 线性探查:重写get方法
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[index].key === key) {    //只是为了确认一下
return table[index].value;
}
}
}
return undefined;
}

// 分离链接:重写remove方法
this.remove = function(key) {
var position = loseloseHashCode(key);

if (table[position] !== undefined) {
if (table[position].key === key) {
table[index] = undefined;
} else {
var index = ++position;
while (table[index] === undefined || table[index].key !== key) {
index++;
}
if (table[index].key === key) {    //只是为了确认一下
table[index] = undefined;
}
}
}
return undefined;
}
}

HashTable.js


HashTable.js

参考书籍:《学习JavaScript数据结构与算法》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: