收集一些学习布隆过滤器和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)
*/