Skip to content

Latest commit

 

History

History
69 lines (66 loc) · 2.63 KB

3A.md

File metadata and controls

69 lines (66 loc) · 2.63 KB

开链式Hash表

有容乃大

解决Hash冲突的一个主流思想是包容,可以用链表将冲突的元素都挂到一起。

type node = linkedlist.Node[string]

type hashSet struct {
    bucket    []*node       //表空间
    size      int
    nextLine  int           //标记待处理的旧表行
    oldBucket []*node       //旧表(仅在rehash过程中有内容)
}

  当然也不能一味地放任下去,否则查询效率就无从谈起了。于是,我们需要限制容积率,并适时扩展表基。扩展需要进行重Hash,这里将重Hash过程分散到此后的每次增删查操作中。

func (s *hashSet) Insert(key string) bool {
    code := hash(key)
    index := code % uint32(len(s.bucket))
    conflict := search(s.bucket[index], key)
    if s.isMoving() {                           //重Hash过程中
        if !conflict {                          //尝试从旧表中查找
            index := code % uint32(len(s.oldBucket))
            conflict = search(s.oldBucket[index], key)
        }
        s.moveLine()                            //推进重Hash过程
    }
    if !conflict {
        unit := new(node)
        unit.Val = key
        unit.Next, s.bucket[index] = s.bucket[index], unit
        s.size++
        if !s.isMoving() && s.isCrowded() {     //检查容积率是否超标
            idx := array.SearchSuccessor(primes, uint32(len(s.bucket)))
            if idx < len(primes) {
                s.resize(primes[idx])           //扩容,即将所有元素重Hash到更大的表中
        }   }
        return true
    }
    return false
}

对应地,删除元素时考虑缩小表基。设置适当的容积率上下界,可以避免在重Hash过程中出现新的重Hash请求。

func (s *hashSet) Remove(key string) bool {
    code, done := hash(key), false
    index := code % uint32(len(s.bucket))
    s.bucket[index], done = remove(s.bucket[index], key)
    if s.isMoving() {
        if !done {                              //尝试从旧表中删除
            index = code % uint32(len(s.oldBucket))
            s.oldBucket[index], done = remove(s.oldBucket[index], key)
        }
        s.moveLine()                            //推进重Hash过程
    }
    if done {
        s.size--
        if !s.isMoving() && s.isWasteful() {
            idx := array.SearchFirstGE(primes, uint32(len(s.bucket))) - 1
            if idx >= 0 {
                s.resize(primes[idx])           //减容
    }   }   }
    return done
}

目录 上一节 下一节