JavaScript数据结构——集合、字典和散列表
2016-03-19 22:34
405 查看
集合、字典和散列表都可以存储不重复的值。
在集合中,我们感兴趣的是每个值本身,并把它当作主要元素。在字典和散列表中,我们用 [键,值] 的形式来存储数据。
集合(Set 类):[值,值]对,是一组由无序且唯一(即不能重复)的项组成的。
字典(Map 类):[键,值]对,也称作映射,其中键名是用来查询特定元素的。
散列(HashTable类/HashMap 类):[键,值]对,是Dictionary类的一种散列表实现方式。散列函数的作用是给定一个键值,然后返回值在表中的地址。散列算法的作用是尽可能快地在数据结构中找到一个值。
在一些编程语言中,还有一种叫作散列集合的实现。散列集合由一个集合构成,但是插入、移除或获取元素时,使用的是散列函数。实现散列集合的不同之处在于,不再添加键值对,而是只插入值而没有键。和集合相似,散列集合只存储唯一的不重复的值。
--------------------------------------------------------------------------
(1)集合方法声明:
首先,使用对象来表示集合。
集合的实现:
HashTable.js
参考书籍:《学习JavaScript数据结构与算法》
在集合中,我们感兴趣的是每个值本身,并把它当作主要元素。在字典和散列表中,我们用 [键,值] 的形式来存储数据。
集合(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数据结构与算法》
相关文章推荐
- JavaScript数据结构——栈和队列
- 每周数据结构【4】递归算法:把B树的所有左右节点进行交换
- JavaScript数据结构——数组
- 7-9-有向无环图拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构4——Java 二叉树 遍历
- hdu 4417(树状数组+离线算法)
- 7-8-无向图的关节点-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
- 7-7-无向网的最小生成树-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构笔记-----查找
- 数据结构的学习(2)(c语言)
- 数据结构与算法-第12章二叉树和其他树-005用迭代方法遍历二叉树
- 数据结构之跳表Skiplist
- 数据结构与算法-第12章二叉树和其他树-004求二叉树的最多结点数及对应的层数
- 数据结构与算法-第12章二叉树和其他树-003求二叉树的高度
- 数据结构笔记-----图
- 数据结构与算法-第12章二叉树和其他树-002克隆二叉树
- 数据结构与算法-第12章二叉树和其他树-001遍历
- 【数据结构与算法】(七) c 语言实现一种快速排序算法
- [数据结构]散列表初识
- java数据结构排序之冒泡实现