add ts supported
This commit is contained in:
parent
c96dd3d565
commit
b8098c4677
106
typescript/06_linkedlist/LRUCache.ts
Normal file
106
typescript/06_linkedlist/LRUCache.ts
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 基于Map和双向链表实现的LRU算法
|
||||
* 使用泛型可以存储多种类型的数据
|
||||
*/
|
||||
class LRUCache<K, V> {
|
||||
private cacheMap: Map<K, LinkedListNode<K, V>>
|
||||
private readonly limit: number
|
||||
private head: LinkedListNode<K, V> | null = null
|
||||
private end: LinkedListNode<K, V> | null = null
|
||||
|
||||
constructor(limit: number) {
|
||||
if (limit <= 0) throw new Error('limit of cache must > 0')
|
||||
this.cacheMap = new Map()
|
||||
this.limit = limit
|
||||
}
|
||||
|
||||
public get(key: K): V | null {
|
||||
const node = this.cacheMap.get(key)
|
||||
if (!node) return null
|
||||
this.refreshNode(node)
|
||||
return node.value
|
||||
}
|
||||
|
||||
public put(key: K, value: V) {
|
||||
const node = this.cacheMap.get(key)
|
||||
// 原缓存不存在则加入到队尾
|
||||
if (!node) {
|
||||
// 大于规定的size则删除最不常用的
|
||||
if (this.cacheMap.size >= this.limit) {
|
||||
const oldKey = this.removeNode(this.head!)
|
||||
this.cacheMap.delete(oldKey)
|
||||
}
|
||||
// 在队尾添加
|
||||
const newNode = new LinkedListNode(key, value)
|
||||
this.addNode(newNode)
|
||||
this.cacheMap.set(key, newNode)
|
||||
} else {
|
||||
node.value = value
|
||||
this.refreshNode(node)
|
||||
}
|
||||
}
|
||||
|
||||
private refreshNode(node: LinkedListNode<K, V>) {
|
||||
if (node === this.end) return
|
||||
this.removeNode(node)
|
||||
this.addNode(node)
|
||||
}
|
||||
|
||||
private removeNode(node: LinkedListNode<K, V>): K {
|
||||
if (node === this.end) {
|
||||
this.end = this.end.prev
|
||||
} else if (node === this.head) {
|
||||
this.head = this.head.next
|
||||
} else {
|
||||
// 这个由于排除了首尾节点
|
||||
node.prev!.next = node.next
|
||||
node.next!.prev = node.prev
|
||||
}
|
||||
return node.key
|
||||
}
|
||||
|
||||
/**
|
||||
* 这里向尾部追加节点
|
||||
* @param node
|
||||
*/
|
||||
private addNode(node: LinkedListNode<K, V>) {
|
||||
if (this.end) {
|
||||
this.end.next = node
|
||||
node.prev = this.end
|
||||
}
|
||||
this.end = node
|
||||
if (this.head === null) {
|
||||
this.head = node
|
||||
}
|
||||
// 消除之前的节点的下一个引用对象,防止无限循环
|
||||
node.next = null
|
||||
}
|
||||
}
|
||||
|
||||
class LinkedListNode<K, V> {
|
||||
key: K
|
||||
value: V
|
||||
next: LinkedListNode<K, V> | null
|
||||
prev: LinkedListNode<K, V> | null
|
||||
|
||||
constructor(
|
||||
key: K,
|
||||
value: V,
|
||||
next: LinkedListNode<K, V> | null = null,
|
||||
prev: LinkedListNode<K, V> | null = null
|
||||
) {
|
||||
this.key = key
|
||||
this.value = value
|
||||
this.next = next
|
||||
this.prev = prev
|
||||
}
|
||||
}
|
||||
|
||||
const cache = new LRUCache<string,string>(3)
|
||||
cache.put('lv','xzw')
|
||||
cache.put('lv2','xzw2')
|
||||
cache.put('lv3','xzw3')
|
||||
cache.put('lv4','xzw4')
|
||||
cache.put('lv5','xzw5')
|
||||
|
||||
console.log(cache)
|
132
typescript/06_linkedlist/LinkedList.ts
Normal file
132
typescript/06_linkedlist/LinkedList.ts
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 双向链表,更加常用设计也更加复杂一些
|
||||
* 需要更多的存储空间和操作复杂度
|
||||
*/
|
||||
import List from './List'
|
||||
|
||||
class LinkedList<T> implements List<T> {
|
||||
size: number = 0
|
||||
private head: LinkedListNode<T> | null = null
|
||||
private last: LinkedListNode<T> | null = null
|
||||
|
||||
findByIndex(index: number): LinkedListNode<T> | null {
|
||||
let p = this.head
|
||||
let pos = 0
|
||||
while (p && pos !== index) {
|
||||
p = p.next
|
||||
pos++
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
findByValue(value: T): LinkedListNode<T> | null {
|
||||
let p = this.head
|
||||
while (p && p.item !== value) {
|
||||
p = p.next
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
insertToHead(value: T): void {
|
||||
let p = this.head
|
||||
const newNode = new LinkedListNode(value)
|
||||
// 没有元素的时候需要初始化头节点和尾节点
|
||||
if (!p) {
|
||||
this.last = this.head = newNode
|
||||
} else {
|
||||
p.prev = newNode
|
||||
newNode.next = p
|
||||
this.head = newNode
|
||||
}
|
||||
this.size++
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的index后面插入节点
|
||||
* @param value 节点的值
|
||||
* @param index 指定的位置
|
||||
*/
|
||||
insertToIndex(value: T, index: number): void {
|
||||
let p = this.head
|
||||
let pos = 0
|
||||
const newNode = new LinkedListNode(value)
|
||||
while (p !== null && pos !== index) {
|
||||
p = p.next
|
||||
pos++
|
||||
}
|
||||
if (p === null) return
|
||||
newNode.next = p.next
|
||||
p.next = newNode
|
||||
newNode.prev = p
|
||||
this.size++
|
||||
}
|
||||
|
||||
insertToTail(value: T): void {
|
||||
let p = this.last
|
||||
const newNode = new LinkedListNode(value)
|
||||
if (p === null) {
|
||||
this.head = this.last = newNode
|
||||
} else {
|
||||
p.next = newNode
|
||||
newNode.prev = p
|
||||
this.last = newNode
|
||||
}
|
||||
|
||||
this.size++
|
||||
}
|
||||
|
||||
remove(value: T): boolean {
|
||||
let p = this.head
|
||||
while (p && p.item !== value) {
|
||||
p = p.next
|
||||
}
|
||||
if (!p) return false
|
||||
if (p.prev) {
|
||||
p.prev.next = p.next
|
||||
} else {
|
||||
this.head = p.next
|
||||
}
|
||||
if (p.next) {
|
||||
p.next.prev = p.prev
|
||||
} else {
|
||||
this.last = p.prev
|
||||
}
|
||||
this.size--
|
||||
return true
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
let ret: string = ''
|
||||
let p = this.head
|
||||
while (p) {
|
||||
ret = `${ret} ${p.item} `
|
||||
p = p.next
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
class LinkedListNode<T> {
|
||||
item: T
|
||||
next: LinkedListNode<T> | null
|
||||
prev: LinkedListNode<T> | null
|
||||
|
||||
constructor(
|
||||
item: T,
|
||||
next: LinkedListNode<T> | null = null,
|
||||
prev: LinkedListNode<T> | null = null
|
||||
) {
|
||||
this.item = item
|
||||
this.next = next
|
||||
this.prev = prev
|
||||
}
|
||||
}
|
||||
|
||||
const linkedList = new LinkedList()
|
||||
linkedList.insertToHead('12')
|
||||
linkedList.insertToHead('haha')
|
||||
linkedList.insertToHead('www')
|
||||
linkedList.insertToTail('zxc')
|
||||
linkedList.insertToIndex('12ooo', 0)
|
||||
linkedList.remove('12oooo')
|
||||
console.log(linkedList.toString())
|
19
typescript/06_linkedlist/List.ts
Normal file
19
typescript/06_linkedlist/List.ts
Normal file
@ -0,0 +1,19 @@
|
||||
interface List<T> {
|
||||
insertToHead(value: T): void
|
||||
|
||||
findByValue(value: T): any
|
||||
|
||||
findByIndex(index: number): any
|
||||
|
||||
insertToIndex(value: T, index: number): void
|
||||
|
||||
remove(value: T): boolean
|
||||
|
||||
insertToHead(value: T): void
|
||||
|
||||
insertToTail(value: T): void
|
||||
|
||||
toString(): string
|
||||
}
|
||||
|
||||
export default List
|
121
typescript/06_linkedlist/SingleLinkedList.ts
Normal file
121
typescript/06_linkedlist/SingleLinkedList.ts
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 1)单链表的插入、删除、查找操作;
|
||||
* 2)链表支持任意类型数据
|
||||
*/
|
||||
import List from './List'
|
||||
|
||||
class SingleLinkedList<T> implements List<T> {
|
||||
// 哨兵头节点
|
||||
private readonly head: SingleNode<T>
|
||||
|
||||
constructor() {
|
||||
this.head = new SingleNode<any>(null)
|
||||
}
|
||||
|
||||
public findByValue(value: T): SingleNode<T> | null {
|
||||
let p = this.head
|
||||
while (p.next != null) {
|
||||
if (p.next.value === value) return p.next
|
||||
p = p.next
|
||||
}
|
||||
return p.next
|
||||
}
|
||||
|
||||
public findByIndex(index: number): SingleNode<T> | null {
|
||||
let p = this.head
|
||||
let pos = 0
|
||||
while (p.next != null && pos !== index) {
|
||||
p = p.next
|
||||
pos++
|
||||
}
|
||||
return p.next
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定的位置插入节点
|
||||
* @param value
|
||||
* @param index
|
||||
*/
|
||||
public insertToIndex(value: T, index: number): void {
|
||||
const newNode = new SingleNode(value)
|
||||
let p = this.head
|
||||
let pos = 0
|
||||
while (p.next != null && pos !== index) {
|
||||
p = p.next
|
||||
pos++
|
||||
}
|
||||
if (p.next == null) return
|
||||
newNode.next = p.next.next
|
||||
p.next.next = newNode
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据值去删除节点
|
||||
* @param value 1 表示删除成功,0 表示删除失败
|
||||
*/
|
||||
public remove(value: T): boolean {
|
||||
let p = this.head
|
||||
while (p.next != null) {
|
||||
if (p.next.value === value) break
|
||||
p = p.next
|
||||
}
|
||||
if (p.next === null) return false
|
||||
p.next = p.next.next
|
||||
return true
|
||||
}
|
||||
|
||||
public insertToHead(value: T): void {
|
||||
const newNode = new SingleNode(value, null)
|
||||
this.insertNodeToHead(newNode)
|
||||
}
|
||||
|
||||
public insertToTail(value: T): void {
|
||||
const newNode = new SingleNode(value, null)
|
||||
this.insertNodeToTail(newNode)
|
||||
}
|
||||
|
||||
private insertNodeToHead(node: SingleNode<T>): void {
|
||||
node.next = this.head.next
|
||||
this.head.next = node
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
let ret: string = ''
|
||||
let p = this.head
|
||||
while (p.next != null) {
|
||||
ret = `${ret} ${p.next.value} `
|
||||
p = p.next
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
/**
|
||||
* 单链表的尾插入比较费时
|
||||
* @param newNode 插入的新节点
|
||||
*/
|
||||
private insertNodeToTail(newNode: SingleNode<T>): void {
|
||||
let p = this.head
|
||||
while (p.next != null) {
|
||||
p = p.next
|
||||
}
|
||||
p.next = newNode
|
||||
}
|
||||
}
|
||||
|
||||
class SingleNode<T> {
|
||||
value: T
|
||||
next: SingleNode<T> | null
|
||||
|
||||
constructor(value: T, next: SingleNode<T> | null = null) {
|
||||
this.value = value
|
||||
this.next = next
|
||||
}
|
||||
}
|
||||
|
||||
const singleLinkedList = new SingleLinkedList<string>()
|
||||
singleLinkedList.insertToTail('god')
|
||||
singleLinkedList.insertToTail('my')
|
||||
// console.log(singleLinkedList.printLinkedList())
|
||||
singleLinkedList.insertToIndex('haha', 1)
|
||||
singleLinkedList.remove('ha1')
|
||||
singleLinkedList.toString()
|
Loading…
Reference in New Issue
Block a user