Skip to content

Commit 4d1ff58

Browse files
Merge pull request #313 from jsrdxzw/master
add typescript supported
2 parents 3e64f88 + 1ebf877 commit 4d1ff58

File tree

5 files changed

+512
-0
lines changed

5 files changed

+512
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* 基于Map和双向链表实现的LRU算法
3+
* 使用泛型可以存储多种类型的数据
4+
*/
5+
class LRUCache<K, V> {
6+
private cacheMap: Map<K, LinkedListNode<K, V>>
7+
private readonly limit: number
8+
private head: LinkedListNode<K, V> | null = null
9+
private end: LinkedListNode<K, V> | null = null
10+
11+
constructor(limit: number) {
12+
if (limit <= 0) throw new Error('limit of cache must > 0')
13+
this.cacheMap = new Map()
14+
this.limit = limit
15+
}
16+
17+
public get(key: K): V | null {
18+
const node = this.cacheMap.get(key)
19+
if (!node) return null
20+
this.refreshNode(node)
21+
return node.value
22+
}
23+
24+
public put(key: K, value: V) {
25+
const node = this.cacheMap.get(key)
26+
// 原缓存不存在则加入到队尾
27+
if (!node) {
28+
// 大于规定的size则删除最不常用的
29+
if (this.cacheMap.size >= this.limit) {
30+
const oldKey = this.removeNode(this.head!)
31+
this.cacheMap.delete(oldKey)
32+
}
33+
// 在队尾添加
34+
const newNode = new LinkedListNode(key, value)
35+
this.addNode(newNode)
36+
this.cacheMap.set(key, newNode)
37+
} else {
38+
node.value = value
39+
this.refreshNode(node)
40+
}
41+
}
42+
43+
private refreshNode(node: LinkedListNode<K, V>) {
44+
if (node === this.end) return
45+
this.removeNode(node)
46+
this.addNode(node)
47+
}
48+
49+
private removeNode(node: LinkedListNode<K, V>): K {
50+
if (node === this.end) {
51+
this.end = this.end.prev
52+
} else if (node === this.head) {
53+
this.head = this.head.next
54+
} else {
55+
// 这个由于排除了首尾节点
56+
node.prev!.next = node.next
57+
node.next!.prev = node.prev
58+
}
59+
return node.key
60+
}
61+
62+
/**
63+
* 这里向尾部追加节点
64+
* @param node
65+
*/
66+
private addNode(node: LinkedListNode<K, V>) {
67+
if (this.end) {
68+
this.end.next = node
69+
node.prev = this.end
70+
}
71+
this.end = node
72+
if (this.head === null) {
73+
this.head = node
74+
}
75+
// 消除之前的节点的下一个引用对象,防止无限循环
76+
node.next = null
77+
}
78+
}
79+
80+
class LinkedListNode<K, V> {
81+
key: K
82+
value: V
83+
next: LinkedListNode<K, V> | null
84+
prev: LinkedListNode<K, V> | null
85+
86+
constructor(
87+
key: K,
88+
value: V,
89+
next: LinkedListNode<K, V> | null = null,
90+
prev: LinkedListNode<K, V> | null = null
91+
) {
92+
this.key = key
93+
this.value = value
94+
this.next = next
95+
this.prev = prev
96+
}
97+
}
98+
99+
const cache = new LRUCache<string,string>(3)
100+
cache.put('lv','xzw')
101+
cache.put('lv2','xzw2')
102+
cache.put('lv3','xzw3')
103+
cache.put('lv4','xzw4')
104+
cache.put('lv5','xzw5')
105+
106+
console.log(cache)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/**
2+
* 双向链表,更加常用设计也更加复杂一些
3+
* 需要更多的存储空间和操作复杂度
4+
*/
5+
import List from './List'
6+
7+
class LinkedList<T> implements List<T> {
8+
size: number = 0
9+
private head: LinkedListNode<T> | null = null
10+
private last: LinkedListNode<T> | null = null
11+
12+
findByIndex(index: number): LinkedListNode<T> | null {
13+
let p = this.head
14+
let pos = 0
15+
while (p && pos !== index) {
16+
p = p.next
17+
pos++
18+
}
19+
return p
20+
}
21+
22+
findByValue(value: T): LinkedListNode<T> | null {
23+
let p = this.head
24+
while (p && p.item !== value) {
25+
p = p.next
26+
}
27+
return p
28+
}
29+
30+
insertToHead(value: T): void {
31+
let p = this.head
32+
const newNode = new LinkedListNode(value)
33+
// 没有元素的时候需要初始化头节点和尾节点
34+
if (!p) {
35+
this.last = this.head = newNode
36+
} else {
37+
p.prev = newNode
38+
newNode.next = p
39+
this.head = newNode
40+
}
41+
this.size++
42+
}
43+
44+
/**
45+
* 在指定的index后面插入节点
46+
* @param value 节点的值
47+
* @param index 指定的位置
48+
*/
49+
insertToIndex(value: T, index: number): void {
50+
let p = this.head
51+
let pos = 0
52+
const newNode = new LinkedListNode(value)
53+
while (p !== null && pos !== index) {
54+
p = p.next
55+
pos++
56+
}
57+
if (p === null) return
58+
newNode.next = p.next
59+
p.next = newNode
60+
newNode.prev = p
61+
this.size++
62+
}
63+
64+
insertToTail(value: T): void {
65+
let p = this.last
66+
const newNode = new LinkedListNode(value)
67+
if (p === null) {
68+
this.head = this.last = newNode
69+
} else {
70+
p.next = newNode
71+
newNode.prev = p
72+
this.last = newNode
73+
}
74+
75+
this.size++
76+
}
77+
78+
remove(value: T): boolean {
79+
let p = this.head
80+
while (p && p.item !== value) {
81+
p = p.next
82+
}
83+
if (!p) return false
84+
if (p.prev) {
85+
p.prev.next = p.next
86+
} else {
87+
this.head = p.next
88+
}
89+
if (p.next) {
90+
p.next.prev = p.prev
91+
} else {
92+
this.last = p.prev
93+
}
94+
this.size--
95+
return true
96+
}
97+
98+
toString(): string {
99+
let ret: string = ''
100+
let p = this.head
101+
while (p) {
102+
ret = `${ret} ${p.item} `
103+
p = p.next
104+
}
105+
return ret
106+
}
107+
}
108+
109+
class LinkedListNode<T> {
110+
item: T
111+
next: LinkedListNode<T> | null
112+
prev: LinkedListNode<T> | null
113+
114+
constructor(
115+
item: T,
116+
next: LinkedListNode<T> | null = null,
117+
prev: LinkedListNode<T> | null = null
118+
) {
119+
this.item = item
120+
this.next = next
121+
this.prev = prev
122+
}
123+
}
124+
125+
const linkedList = new LinkedList()
126+
linkedList.insertToHead('12')
127+
linkedList.insertToHead('haha')
128+
linkedList.insertToHead('www')
129+
linkedList.insertToTail('zxc')
130+
linkedList.insertToIndex('12ooo', 0)
131+
linkedList.remove('12oooo')
132+
console.log(linkedList.toString())

typescript/06_linkedlist/List.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
interface List<T> {
2+
insertToHead(value: T): void
3+
4+
findByValue(value: T): any
5+
6+
findByIndex(index: number): any
7+
8+
insertToIndex(value: T, index: number): void
9+
10+
remove(value: T): boolean
11+
12+
insertToHead(value: T): void
13+
14+
insertToTail(value: T): void
15+
16+
toString(): string
17+
}
18+
19+
export default List
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* 1)单链表的插入、删除、查找操作;
3+
* 2)链表支持任意类型数据
4+
*/
5+
import List from './List'
6+
7+
class SingleLinkedList<T> implements List<T> {
8+
// 哨兵头节点
9+
private readonly head: SingleNode<T>
10+
11+
constructor() {
12+
this.head = new SingleNode<any>(null)
13+
}
14+
15+
public findByValue(value: T): SingleNode<T> | null {
16+
let p = this.head
17+
while (p.next != null) {
18+
if (p.next.value === value) return p.next
19+
p = p.next
20+
}
21+
return p.next
22+
}
23+
24+
public findByIndex(index: number): SingleNode<T> | null {
25+
let p = this.head
26+
let pos = 0
27+
while (p.next != null && pos !== index) {
28+
p = p.next
29+
pos++
30+
}
31+
return p.next
32+
}
33+
34+
/**
35+
* 向指定的位置插入节点
36+
* @param value
37+
* @param index
38+
*/
39+
public insertToIndex(value: T, index: number): void {
40+
const newNode = new SingleNode(value)
41+
let p = this.head
42+
let pos = 0
43+
while (p.next != null && pos !== index) {
44+
p = p.next
45+
pos++
46+
}
47+
if (p.next == null) return
48+
newNode.next = p.next.next
49+
p.next.next = newNode
50+
}
51+
52+
/**
53+
* 根据值去删除节点
54+
* @param value 1 表示删除成功,0 表示删除失败
55+
*/
56+
public remove(value: T): boolean {
57+
let p = this.head
58+
while (p.next != null) {
59+
if (p.next.value === value) break
60+
p = p.next
61+
}
62+
if (p.next === null) return false
63+
p.next = p.next.next
64+
return true
65+
}
66+
67+
public insertToHead(value: T): void {
68+
const newNode = new SingleNode(value, null)
69+
this.insertNodeToHead(newNode)
70+
}
71+
72+
public insertToTail(value: T): void {
73+
const newNode = new SingleNode(value, null)
74+
this.insertNodeToTail(newNode)
75+
}
76+
77+
private insertNodeToHead(node: SingleNode<T>): void {
78+
node.next = this.head.next
79+
this.head.next = node
80+
}
81+
82+
public toString(): string {
83+
let ret: string = ''
84+
let p = this.head
85+
while (p.next != null) {
86+
ret = `${ret} ${p.next.value} `
87+
p = p.next
88+
}
89+
return ret
90+
}
91+
92+
/**
93+
* 单链表的尾插入比较费时
94+
* @param newNode 插入的新节点
95+
*/
96+
private insertNodeToTail(newNode: SingleNode<T>): void {
97+
let p = this.head
98+
while (p.next != null) {
99+
p = p.next
100+
}
101+
p.next = newNode
102+
}
103+
}
104+
105+
class SingleNode<T> {
106+
public value: T
107+
public next: SingleNode<T> | null
108+
109+
constructor(value: T, next: SingleNode<T> | null = null) {
110+
this.value = value
111+
this.next = next
112+
}
113+
}
114+
115+
const singleLinkedList = new SingleLinkedList<string>()
116+
singleLinkedList.insertToTail('god')
117+
singleLinkedList.insertToTail('my')
118+
// console.log(singleLinkedList.printLinkedList())
119+
singleLinkedList.insertToIndex('haha', 1)
120+
singleLinkedList.remove('ha1')
121+
singleLinkedList.toString()

0 commit comments

Comments
 (0)