Skip to content

Commit

Permalink
add ts supported
Browse files Browse the repository at this point in the history
  • Loading branch information
許 志偉 authored and 許 志偉 committed May 16, 2019
1 parent c96dd3d commit b8098c4
Show file tree
Hide file tree
Showing 4 changed files with 378 additions and 0 deletions.
106 changes: 106 additions & 0 deletions typescript/06_linkedlist/LRUCache.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 132 additions & 0 deletions typescript/06_linkedlist/LinkedList.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions typescript/06_linkedlist/List.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 121 additions & 0 deletions typescript/06_linkedlist/SingleLinkedList.ts
Original file line number Diff line number Diff line change
@@ -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()

0 comments on commit b8098c4

Please sign in to comment.