map实现
为什么用map
而不用{...}
map
不仅能存储, 还有顺序{...}
只能存储, 没有顺序
js
class LRU {
private maxLength = 1;
private hash = new Map();
constructor(length = 1) {
if (length < 1) throw new Error("length 不能小于1");
this.maxLength = length;
}
set(key: any, value: any) {
if (this.hash.has(key)) {
this.hash.delete(key);
}
this.hash.set(key, value);
if (this.hash.size > this.maxLength) {
const oldestKey = this.hash.keys().next().value;
this.hash.delete(oldestKey);
}
}
get(key: any) {
const v = this.hash.get(key);
this.hash.delete(key);
this.hash.set(key, v);
return v;
}
}
测试: set更新排序
js
const lru = new LRU(2);
lru.set(1, 100);
lru.set(2, 200);
lru.set(1, 101);
lru.set(3, 300);
console.log(lru.get(1)); // 101
console.log(lru.get(2)); // undefined
console.log(lru.get(3)); // 300
测试: get更新排序
js
const lru = new LRU(2);
lru.set(1, 100);
lru.set(2, 200);
lru.get(1);
lru.set(3, 300);
console.log(lru.get(1)); // 100
console.log(lru.get(2)); // undefined
console.log(lru.get(3)); // 300
双向链表
- 用双向链表仿了一个
MyMap
- 如何仿一个map
- 既能快速查询
hash[key]
- 又能有顺序
- 既能快速查询
js
// 下面是MyMap的数据结构
// 既能快速查询, 又有顺序
const hash = {
key1: item1
🔽 // item1.next = item2
key2: item2
🔽 // item2.next = item3
key3: item3
🔽 // item3.next = item4
key4: item4
🔽 // item4.next = item5
key5: item5
}
代码实现
js
class LRU {
private maxLength = 1;
private hash = new MyMap();
constructor(length = 1) {
if (length < 1) throw new Error("length 不能小于1");
this.maxLength = length;
}
set(key: any, value: any) {
if (this.hash.has(key)) {
this.hash.delete(key);
}
this.hash.set(key, value);
if (this.hash.size > this.maxLength) {
const oldestKey = this.hash.head?.key;
this.hash.delete(oldestKey);
}
}
get(key: any) {
const v = this.hash.get(key);
this.hash.delete(key);
this.hash.set(key, v);
return v;
}
}
class ListNode {
key: string;
value: any;
next: ListNode | null = null;
prev: ListNode | null = null;
constructor(key: string, value: any) {
this.key = key;
this.value = value;
}
}
class MyMap {
data: { [key: string]: ListNode } = {};
size: number = 0;
head: ListNode | null = null;
tail: ListNode | null = null;
has(key: string) {
return this.data[key] ? true : false;
}
// 移动到末尾, 末尾是最新鲜的
move2Tail(node: ListNode) {
if (this.tail === node) return; // 已经是最新鲜的了
node = this.cut(node);
const prevNode = this.tail;
if (prevNode) prevNode.next = node;
node.prev = prevNode;
this.tail = node;
}
add(node: ListNode) {
this.move2Tail(node);
this.data[node.key] = node;
this.size++;
if (this.size === 1) this.head = node; // 添加的第一个
}
delete(key?: string) {
if (!key) return;
const node = this.data[key];
if (node) this.cut(node);
delete this.data[key];
this.size--;
}
get(key: string) {
const target = this.data[key];
if (!target) return;
// 末尾的是最新鲜的
if (target !== this.tail) {
this.move2Tail(target);
}
return target.value;
}
set(key: string, value: any) {
const target = this.data[key];
if (!target) {
const newNode = new ListNode(key, value);
this.add(newNode);
} else {
target.value = value;
this.move2Tail(target);
}
}
cut(node: ListNode) {
const preNode = node.prev;
const nextNode = node.next;
if (this.head === node) {
this.head = node.next;
}
if (this.tail === node) {
this.tail = node.prev;
}
if (preNode) preNode.next = nextNode;
if (nextNode) nextNode.prev = preNode;
node.prev = null;
node.next = null;
return node;
}
}