一、字典
字典(dictionary)是一些元素的集合。
字典的特点:①字典是通过见制度来保存的
②字典的主要特点是一一对应的关系.、
③字典里面的键不允许重复,但是值可以,key也是无序的
二、字典和映射的关系:
有些编程语言中称这种映射关系为字典,因为它确实和生活中的字典比较相似.(比如Swift中Dictionary, Python中的dict)
有些编程语言中称这种映射关系为Map,注意Map在这里不要翻译成地图,而是翻译成映射.(比如Java中就有HashMap&TreeMap等)
三、字典和数组:
字典和数组对比的话,字典可以非常方便的通过key来搜索对应的value, key可以包含特殊含义,,也更容易被人们记住字典和对象:
很多编程语言(比如Java)中对字典和对象区分比较明显,对象通常是一种在编译期就确定下来的结构,不可以动态的添加或者删除属性.而字典通常会使用类似于哈希表的数据结构去实现一种可以动态的添加数据的结构.
但是在JavaScript中,似乎对象本身就是一种字典.所有在早期的JavaScript中,没有字典这种数据类型,因为你完全可以使用对象去代替.
四、哈希表
哈希表通常是基于数组进行实现的,但是相对于数组,它也很多的优势:它可以提供非常快速的插入-删除-查找操作
无论多少数据,插入和删除值需要接近常量的时间:即O(1)的时间级.实际上,只需要几个机器指令即可完成口哈希表的速度比树还要快,基本可以瞬间查找到想要的元素
哈希表相对于树来说编码要容易很多.
哈希表相对于数组的一些不足:
哈希表中的数据是没有顺序的,所以不能以一种固定的方式(比如从小到大)来遍历其中的元素.通常情况下,哈希表中的key是不允许重复的,不能放置相同的key,用于保存不同的元素.
什么是哈希函数:可以输入任意的文本,视频,音乐文件或者是任何类型的数据,函数的输出是一个固定长度的数据。
五、哈希表的各种思考
1.什么是哈希化?什么是哈希地址?什么是哈希表?
2.冲突?
六、哈希表不同方法
1.链地址法
2.深入开放地址法
开放地址法的主要工作方式是寻找空白的单元格来添加重复的数据.
2.1线性探测
2 .2二次探测
2.3再哈希法
七、不同方法的效率
1.链地址法效率最高因为他的装填因子(loadFactor)最大
2.线性探测
3.二次探测和在哈希法
八、哈希函数的实现
function hashFunc(str,size){
var hashCode=0
for(var i=0;i<str.length;i++){
// 霍纳算法随机取得37可以是别的但是最好是37
hashCode=37*hashCode+str.charCodeAt(i)
}
// 取余操作
var index=hashCode%size
return index
}
console.log(hashFunc('abc',7))
console.log(hashFunc('nba',7))
console.log(hashFunc('mba',7))
console.log(hashFunc('cba',7))
增加修改操作的实现
//增加和修改
hashTable.prototype.put = function (key, value) {
//1.计算放在哪
var index = this.hashFunc(key, this.limit)
//2.拿到所在索引下面的桶也就是那块来装数值对的链子
var bucket = this.storage[index]
// 判断桶是否为空如果为空我们需要创建它
if (bucket == null) {
//如果为空说明没有元素
bucket = [];
// 将桶设置为数组,之后确保storage下标一定会有一个桶
this.storage[index] = bucket
}
//判断是否要修改数据
// 循环遍历拿到桶里面的值
for (var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
//如果第一个元素就是我们要查找的元素
if (tuple[0] == key) {
tuple[1] = value;
return
}
}
// 判断是否要添加数据
bucket.push([key, value])
this.count += 1
}
var tb = new hashTable()
tb.put("abc", "job'")
tb.put("nba", "mogo")
tb.put("mba", "ojn")
获取操作的实现
//获取方法
hashTable.prototype.get = function (key) {
//获取下标值
var index = this.hashFunc(key, this.limit)
//查找下标值下面的那个桶
var bucket = this.storage[index]
// 判断桶是否为空
if (bucket == null) {
return null
}
for (var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
if (tuple[0] == key)
return tuple[1]
}
return null
}
删除操作的实现
hashTable.prototype.remove = function (key) {
var index = this.hashFunc(key, this.limit)
var bucket = this.storage[index]
if (bucket == null) return null
for (var i = 0; i < bucket.length; i++) {
var tuple = bucket[i]
if (tuple[0] == key) {
bucket.splice(i, 1)
return tuple[1]
this.count--
}
}
return null
}
hashTable.prototype.isEmpty = function () {
return this.count == 0
}
hashTable.prototype.size = function () {
return this.count
}
hashTable.prototype.getItems = function () {
return this.storage
}
哈希表的扩容
哈希表扩容操作的实现
hashTable.prototype.resize = function (newLimit) {
//把原来的storage里面的数据保存在oldStorage里
var oldSortage = this.storage
// 重置这些配置项
this.storage = []
this.count = 0
this.limit = old
// 遍历旧数据
for (var i = 0; i < oldSortage.length; i++) {
var bucket = oldSortage[i]
if (bucket == null) continue
//bucket里面要有数据取出,重新插入进去
for (var j = 0; j < bucket.length; j++) {
var tuple = bucket[i]
this.put(tuple[0], tuple[1])
}
}
bucket.push([key, value])
this.count += 1
}
普通方法判断是否为质数
function isPrime(num) {
for (var i = 2; i < num; i++) {
if (num % i == 0) {
return false
}
}
return true
}
console.log(isPrime(3));
console.log(isPrime(15));
console.log(isPrime(11));
高效法判断质数
function isPrime(num){
var temp=parseInt(Math.sqrt(num))
for(var i=2;i<=temp;i++){
if(num%i==0){
return false
}
}
return true
}
console.log(isPrime(3));
console.log(isPrime(15));
console.log(isPrime(11));
更改前面实现的扩容操作需要添加一段改成质数的方法
hashTable.prototype.getPrime=function(num){
while(!(isPrime(num))){
num++
}
return num
}