散列表 -- js

散列表定义-百度百科
我的理解是:我有一条数据要存 name:xxx,如果直接存,以后数据越来越多的时候,可能要遍历查找,现在我按照一定规则(散列函数)转换成地址,下次读取时,只要按照这个这个散列函数直接访问地址,快速返回我要的key-value.不需要遍历了。
比如 a:1 => 变身=>[dajdhkadhk]:1=>读取=>a:1

1 创建散列表

function HashTable() {
  var table = []
  // 散列函数
  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)
    console.log(position+'-'+key)
    table[position]=value
  }
// 读取某项
  this.get=function(key){
    return table[loseloseHashCode(key)]
  }
//删除某项
 this.remove=function(key){
table[loseloseHashCode(key)] =undefind
}
 this.print=function(){
      for(let i=0;i<table.length;i++){
        if(table[i]!==undefined){
          console.log(i+':'+table[i])
        }
      }
    }
}

运行能读,能存,能删
但是当key转换成的散列值与之前的相同时,值将会被覆盖。


image.png

print一下


image.png

2 解决冲突

2.1分离链接
思路,table[position]变成一个链表

function HashTable() {
    var table = []
    // 散列函数
    var loseloseHashCode = function(key){
        var hash = 0
        for(var i =0 ;i<key.length;i++){
            hash+=key.charCodeAt(i)
        }
        return hash % 37
    }
    var ValuePair = function(key,value){
        this.key = key
        this.value = value
        this.toString = function(){
            return '['+this.key+'-'+this.value+']'
        }
    }
    // 向散列表中增加一个新的项
    this.put = function (key,value){
        var position = loseloseHashCode(key)
        console.log(position+':'+key)
        if(table[position] ==undefined){
            table[position]=new LinkedList()
        }
        table[position].append(new ValuePair(key,value))
    }
// 读取某项
    this.get=function(key){
        var position = loseloseHashCode(key)
        if(table[position]!==undefined){
            let 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
    }
//删除某项
    this.remove=function(key){
        var position = loseloseHashCode(key)
        if (table[position] !== undefined) {
          let 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
          }
        }
        return false
    }
    this.print=function(){
        for(let i=0;i<table.length;i++){
            if(table[i]!==undefined){
                console.log(i+':'+table[i])
            }
        }
    }
}

2.2线性探查
table[position]存在=>table[position+1]={key,value}
模拟过程:
h= new HashTable()
1,插入
考虑一个情况1,2,4,5坑位都占好了,
现在position假设为3,table[3]此时为undefined,table[3]={key:'name',value:zlj}
插入成功
现在我又要插数据了,position还是为3,3号坑位已经被占了,我要向后寻找坑位,6号坑位是空的,tablep[6]={key:'age',value:26}
插入成功
2,查找:
我要h.get('age')
根据我散列转换函数position就是3呀,
现在来核对一下是否正确
table[3].key :name 不是age,
向下一个坑位寻找,下一个坑位有两种情况,要么被占领了,要么没有被占,只要下一个坑位的不是{key:age}就一直向后寻找,直到找到。
如果一直找不到怎么办,所以要在初始的时候判断一下table[position]===undefind
思考:h.get('age')只会是两种结果,要么存在值,要么为undefind
,存在值要么在position的某个位置,要么在999999+的位置,反正肯定能找到的,因为我们插值就是这样插得,这个坑位被占,一直向后寻找空的坑位,要么这个坑位根本没有占。

function HashTable() {
    var table = []
    // 散列函数
    var loseloseHashCode = function(key){
        var hash = 0
        for(var i =0 ;i<key.length;i++){
            hash+=key.charCodeAt(i)
        }
        return hash % 37
    }
    var ValuePair = function(key,value){
        this.key = key
        this.value = value
        this.toString = function(){
            return '['+this.key+'-'+this.value+']'
        }
    }
    // 向散列表中增加一个新的项
    this.put = function (key,value){
        var position = loseloseHashCode(key)
        // 当前index没用被占用
        if (table[position] == undefined) {
            table[position] = new ValuePair(key,value)
        } else {
            // 当前index 已经被占用了
            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 {
                let index = ++position
                // 找到
                while(table[index] ==undefined ||table[index].key !== key) {
                    index++
                }
                if(table[index].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
                return true
            } else {
                let index = ++position
                // 找到
                while(table[index] ==undefined ||table[index].key !== key) {
                    index++
                }
                if(table[index].key === key){
                    table[index] = undefined
                    return true
                }
            }
        }
        return false
    }
    this.print=function(){
        for(let i=0;i<table.length;i++){
            if(table[i]!==undefined){
                console.log(i+':'+table[i])
            }
        }
    }
}
h = new HashTable()
h.put('Mindy','aa')
h.put('Paul','bb')
console.log(h.get('Paul'),h.get('Mindy'))
console.log(h.remove('Paul'),h.remove('Mindy'))
console.log(h.get('Paul'),h.get('Mindy'))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,362评论 8 265
  • 一曲秦腔唱出了西安的韵律,一座王陵再现了历史的久远与庄严,一池华清水沐浴了帝王爱情的忠烈,一处碑林诠释了汉字...
    雅娴阅读 384评论 1 0
  • 2017年6月6日,这是2017年高考的前一天,也是炎炎夏日的平常一天。 你那里或许嘉树清圆,夏木苍翠,枝叶上的粼...
    清大紫育阅读 168评论 0 0
  • 看清楚生命无非是一个过程 无常才是常态 也就会更加从容的去面对生活
    茉莉桃子阅读 139评论 0 0