用JS设计布隆过滤器、LRU缓存

本文深入解析布隆过滤器的工作原理及其实现细节,包括位图映射、错误率计算等关键概念,并提供了一种使用JS设计的数据结构代码。同时,文章还介绍了LRU缓存策略,通过自定义链表节点和双链表结构,实现了高效的缓存管理和数据访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

收集一些学习布隆过滤器和LUR缓存的时候看到的文章,还有如何用JS设计数据结构的代码

布隆过滤器

详解布隆过滤器
实现:https://www.jianshu.com/p/f75b6bcb4e57

/**
 * BoolmFilter
 * maxKeys:最大数量
 * errorRate:错误率
 *
 */
function BoolmFilter (maxKeys, errorRate) {
  // 布隆过滤器位图映射变量
  this.bitMap = [];
  // 布隆过滤器中最多可放的数量
  this.maxKeys = maxKeys;
  // 布隆过滤器错误率
  this.errorRate = errorRate;
  // 位图变量的长度,需要根据maxKeys和errorRate来计算
  this.bitSize = Math.ceil(maxKeys * (-Math.log(errorRate) / (Math.log(2) * Math.log(2)) ));
  // 哈希数量
  this.hashCount = Math.ceil(Math.log(2) * (this.bitSize / maxKeys));
  // 已加入元素数量
  this.keyCount = 0;

  // 初始化位图数组
  // for (let i = Math.ceil(this.bitSize / 31) - 1; i >=0; i--) {
  //   this.bitMap[i] = 0;
  // }
}

/**
 * 设置位
 *
 */
BoolmFilter.prototype.bitSet = function (bit) {
  // this.bitMap |= (1<<bit);
  // bitSize
  let numArr = Math.floor(bit / 31),
      numBit = Math.floor(bit % 31);
  this.bitMap[numArr] |= (1<<numBit);
  // this.bitMap[bit] = 1;
}

/**
 * 读取位
 *
 */
BoolmFilter.prototype.bitGet = function (bit) {
  // return this.bitMap &= (1<<bit);
  let numArr = Math.floor(bit / 31),
      numBit = Math.floor(bit % 31);
  return this.bitMap[numArr] &= (1<<numBit);
  // return this.bitMap[bit];
}

/**
 * 加入布隆过滤器
 *
 */
BoolmFilter.prototype.add = function (key) {
  if (this.contain(key)) {
    return -1;
  }

  let hash1 = MurmurHash(key, 0, 0),
      hash2 = MurmurHash(key, 0, hash1);  
  
  for (let i = 0; i < this.hashCount; i++) {
    this.bitSet(Math.abs( Math.floor((hash1 + i * hash2) % (this.bitSize)) ));  
  }  
  
  this.keyCount++;
}

/**
 * 检测是否已经存在
 *
 */
BoolmFilter.prototype.contain = function (key) {
  let hash1 = MurmurHash(key, 0, 0),
      hash2 = MurmurHash(key, 0, hash1);  
  
  for (let i = 0; i < this.hashCount; i++) {  
    if ( !this.bitGet(Math.abs( Math.floor((hash1 + i * hash2) % (this.bitSize)) )) ) {
      return false;
    }  
  }

  return true;
}

LRU缓存

在这里插入图片描述

// 链表节点
class Node{
    constructor(key,val){
        this.key = key;
        this.val = val;
    }
}
// 双链表
class DoubleList{
    // 初始化头、尾节点、链表最大容量
    constructor(){
        this.head = new Node(0,0);
        this.tail = new Node(0,0);
        this.size = 0;
        this.head.next = this.tail;
        this.tail.prev = this.head;
    }
    // 在链表头部添加节点
    addFirst(node){
        node.next = this.head.next;
        node.prev = this.head;
        this.head.next.prev = node;
        this.head.next = node;
        this.size++;
    }
    // 删除链表中存在的node节点
    remove(node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
        this.size--;
    }
    // 删除链表中最后一个节点,并返回该节点
    removeLast(){
        // 链表为空
        if(this.tail.prev == this.head){
            return null;
        }
        let last = this.tail.prev;
        this.remove(last);
        return last;
    }
}
/**
* @param {number} capacity
*/
var LRUCache = function(capacity) {
    this.cap = capacity;
    this.map = new Map();
    this.cache = new DoubleList();
};

/** 
* @param {number} key
* @return {number}
*/
LRUCache.prototype.get = function(key) {
    let map = this.map;
    if(!map.has(key)){
        return -1;
    }
    let val = map.get(key).val;
    // 最近访问数据置前
    this.put(key,val);
    return val;
};

/** 
* @param {number} key 
* @param {number} value
* @return {void}
*/
LRUCache.prototype.put = function(key, value) {
    let cache = this.cache;
    let map = this.map;
    let node = new Node(key,value);
    if(map.has(key)){
        // 删除旧的节点,新的插到头部
        cache.remove(map.get(key));
    }else{
        if(this.cap == cache.size){
            // 删除最后一个
            let last = cache.removeLast();
            map.delete(last.key);
        }
    }
    // 新增头部
    cache.addFirst(node);
    // 更新 map 映射
    map.set(key,node);
};

/** 
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值