Skip to content

Commit 542b066

Browse files
Merge pull request #314 from jsrdxzw/master
add stack and queue
2 parents 4d1ff58 + d6f65ed commit 542b066

File tree

7 files changed

+369
-3
lines changed

7 files changed

+369
-3
lines changed

typescript/07_linkedlist/LinkedListAlog.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class LinkedListAlog {
3333
let slow: SingleNode<T> | null = list
3434
while (fast && fast.next) {
3535
fast = fast.next.next
36-
slow = slow!!.next
36+
slow = slow!.next
3737
if (fast === slow) return true
3838
}
3939
return false
@@ -68,7 +68,7 @@ class LinkedListAlog {
6868
let slow = list
6969
while (fast && fast.next) {
7070
fast = fast.next.next
71-
slow = slow.next!!
71+
slow = slow.next!
7272
}
7373
return slow
7474
}
@@ -121,7 +121,6 @@ class SingleNode<T> {
121121
}
122122
}
123123

124-
125124
const node1 = new SingleNode(1)
126125
node1.next = new SingleNode(3)
127126
node1.next.next = new SingleNode(5)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/**
2+
* 基于单向链表实现栈结构
3+
*/
4+
export class Stack<T> {
5+
private node: LinkedNode<T> | null = null
6+
size: number = 0
7+
8+
public push(value: T) {
9+
if (!value) return
10+
const newNode = new LinkedNode(value)
11+
if (!this.node) {
12+
this.node = newNode
13+
} else {
14+
newNode.next = this.node
15+
this.node = newNode
16+
}
17+
this.size++
18+
}
19+
20+
public pop(): T | null {
21+
if (!this.node) {
22+
return null
23+
}
24+
const value = this.node.value
25+
this.node = this.node.next
26+
this.size--
27+
return value
28+
}
29+
}
30+
31+
/**
32+
* 单向链表
33+
*/
34+
class LinkedNode<T> {
35+
value: T
36+
next: LinkedNode<T> | null
37+
38+
constructor(value: T, next: LinkedNode<T> | null = null) {
39+
this.value = value
40+
this.next = next
41+
}
42+
}
43+
44+
/**
45+
* 使用双栈结构实现浏览器的前进后退
46+
*/
47+
class Browser<T> {
48+
// 存放后退的所有历史url
49+
private backStack: Stack<T>
50+
// 存放前进的所有url
51+
private forwardStack: Stack<T>
52+
private current: T
53+
54+
constructor(current: T) {
55+
this.backStack = new Stack<T>()
56+
this.forwardStack = new Stack<T>()
57+
this.current = current
58+
}
59+
60+
public back(): T | null {
61+
if (this.backStack.size > 0) {
62+
this.forwardStack.push(this.current)
63+
this.current = this.backStack.pop()!
64+
return this.getCurrentPage()
65+
}
66+
return null
67+
}
68+
69+
public forward(): T | null {
70+
if (this.forwardStack.size > 0) {
71+
this.backStack.push(this.current)
72+
this.current = this.forwardStack.pop()!
73+
return this.getCurrentPage()
74+
}
75+
return null
76+
}
77+
78+
/**
79+
* 在网页上点击一个链接
80+
* @param value
81+
*/
82+
public linkUrl(value: T) {
83+
this.current && this.backStack.push(this.current)
84+
this.current = value
85+
}
86+
87+
public getCurrentPage(): T {
88+
return this.current
89+
}
90+
}
91+
92+
const browser = new Browser('www.baidu.com')
93+
browser.linkUrl('www.yuanzhoucehui.com')
94+
browser.linkUrl('www.github.com/jsrdxzw')
95+
// browser.back()
96+
// www.github.com/jsrdxzw
97+
console.log(browser.getCurrentPage())
98+
browser.back()
99+
// www.yuanzhucehui.com
100+
console.log(browser.getCurrentPage())
101+
browser.back()
102+
// www.baidu.com
103+
console.log(browser.getCurrentPage())
104+
browser.back()
105+
// www.baidu.com
106+
console.log(browser.getCurrentPage())
107+
browser.forward()
108+
// www.yuanzhucehui.com
109+
console.log(browser.getCurrentPage())
110+
browser.forward()
111+
// www.github.com/jsrdxzw
112+
console.log(browser.getCurrentPage())
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* 基于数组的循环队列
3+
* 为了方便判断队列为空的情况,这里最好引入元素个数
4+
*/
5+
class CircularQueue<T> {
6+
private items: T[] = []
7+
private readonly n: number = 0
8+
private head: number = 0
9+
private tail: number = 0
10+
// 队列的实际元素大小
11+
size: number = 0
12+
13+
14+
constructor(capacity: number) {
15+
this.n = capacity
16+
}
17+
18+
public enqueue(item: T): boolean {
19+
// 表示队列已经满了
20+
if (this.size === this.n) return false
21+
this.items[this.tail] = item
22+
this.tail = (this.tail + 1) % this.n
23+
this.size++
24+
return true
25+
}
26+
27+
public dequeue(): T | null {
28+
if (!this.size) return null
29+
const item = this.items[this.head]
30+
this.head = (this.head + 1) % this.n
31+
this.size--
32+
return item
33+
}
34+
}
35+
36+
const circularQueue = new CircularQueue<number>(3)
37+
circularQueue.enqueue(1)
38+
circularQueue.enqueue(2)
39+
circularQueue.enqueue(3)
40+
circularQueue.enqueue(4)
41+
42+
const value = circularQueue.dequeue()
43+
const value1 = circularQueue.dequeue()
44+
const value2 = circularQueue.dequeue()
45+
const value3 = circularQueue.dequeue()
46+
47+
// null
48+
console.log(value3)
49+
// 0
50+
console.log(circularQueue.size)
51+

typescript/09_queue/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
### 队列
2+
3+
由于js语言天生就可以使用array数组来实现栈和队列等结构:
4+
```javascript
5+
// 模拟数组队列
6+
const queue = []
7+
queue.push(1) // 向数组尾部添加数据
8+
queue.shift() //数组头部去除数据,并返回
9+
```
10+
这里我们使用链表来实现队列结构
11+
12+
队列分为无限队列和循环队列

typescript/09_queue/SimpleQueue.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* 使用链表实现简单队列
3+
*/
4+
class SimpleQueue<T> {
5+
private head: LinkedNode<T> | null = null
6+
private tail: LinkedNode<T> | null = null
7+
8+
/**
9+
* 入队,插入队尾
10+
* @param value
11+
*/
12+
public enqueue(value: T) {
13+
if (!this.tail) {
14+
this.head = this.tail = new LinkedNode<T>(value)
15+
} else {
16+
const newNode = new LinkedNode<T>(value)
17+
this.tail.next = newNode
18+
this.tail = newNode
19+
}
20+
}
21+
22+
/**
23+
* 出队,在队头删除
24+
*/
25+
public dequeue(): T | null {
26+
if (!this.head) return null
27+
const value = this.head.value
28+
this.head = this.head.next
29+
return value
30+
}
31+
32+
public printAll(): string {
33+
let p = this.head
34+
let res = ''
35+
while (p) {
36+
res = `${res} ${p.value}`
37+
p = p.next
38+
}
39+
return res
40+
}
41+
}
42+
43+
/**
44+
* 单向链表
45+
*/
46+
class LinkedNode<T> {
47+
value: T
48+
next: LinkedNode<T> | null
49+
50+
constructor(value: T, next: LinkedNode<T> | null = null) {
51+
this.value = value
52+
this.next = next
53+
}
54+
}
55+
56+
const queue = new SimpleQueue()
57+
queue.enqueue(1)
58+
queue.enqueue(2)
59+
queue.enqueue(3)
60+
queue.dequeue()
61+
queue.dequeue()
62+
console.log(queue.printAll())
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* 递归求解爬楼梯问题
3+
*/
4+
5+
/**
6+
* 最开始版本的递归算法
7+
* @param n
8+
*/
9+
function fn(n: number): any {
10+
if (n === 1) return 1
11+
if (n === 2) return 2
12+
return fn(n - 1) + fn(n - 2)
13+
}
14+
15+
const res1 = fn(10)
16+
// 89
17+
console.log(res1)
18+
19+
/**
20+
* 使用depth结合js的闭包特性实现限制函数调用次数的功能
21+
* @param depth 递归的深度
22+
*/
23+
function fnWithDepth(depth: number) {
24+
return function fn(n: number): any {
25+
depth++
26+
if (depth > 1000) throw new Error('function stack is too deep!')
27+
if (n === 1) return 1
28+
if (n === 2) return 2
29+
return fn(n - 1) + fn(n - 2)
30+
}
31+
}
32+
33+
const res2 = fnWithDepth(3)(10)
34+
// 89
35+
console.log(res2)
36+
37+
/**
38+
* 通过map来存储已经计算过的值,避免递归重复计算
39+
*/
40+
function fnWithMap() {
41+
const map = new Map<number, number>()
42+
return function fn(n: number): any {
43+
if (n === 1) return 1
44+
if (n === 2) return 2
45+
if (map.has(n)) {
46+
return map.get(n)
47+
}
48+
const ret = fn(n - 1) + fn(n - 2)
49+
map.set(n, ret)
50+
return ret
51+
}
52+
}
53+
54+
const res3 = fnWithMap()(10)
55+
console.log(res3)

typescript/11_sorts/simpleSort.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* 简单的排序,分为冒泡和插入排序
3+
* 注意他们都是稳定的排序,并且是原地排序
4+
* 一般情况下更推荐使用插入排序,因为它所需要的操作更少
5+
* 这里使用简单工厂创建我们的排序算法
6+
*/
7+
8+
/**
9+
* 排序的枚举类型
10+
*/
11+
enum SortType {
12+
BubbleSort,
13+
InsertSort
14+
}
15+
16+
interface SortAlgo {
17+
sort(array: number[]): void
18+
}
19+
20+
class BubbleSort implements SortAlgo {
21+
sort(array: number[]) {
22+
for (let i = 0; i < array.length; i++) {
23+
let flag = false
24+
for (let j = 0; j < array.length; j++) {
25+
if (array[j] > array[j + 1]) {
26+
const temp = array[j]
27+
array[j] = array[j + 1]
28+
array[j + 1] = temp
29+
flag = true
30+
}
31+
}
32+
if (!flag) {
33+
break
34+
}
35+
}
36+
}
37+
}
38+
39+
class InsertSort implements SortAlgo {
40+
sort(array: number[]) {
41+
for (let i = 1; i < array.length; i++) {
42+
let j = i - 1
43+
const temp = array[i]
44+
for (; j >= 0; j--) {
45+
if (array[j] > array[j + 1]) {
46+
array[j + 1] = array[j]
47+
} else {
48+
// 这个说明之前的已经排好了,没必要继续比较
49+
break
50+
}
51+
}
52+
array[j + 1] = temp
53+
}
54+
}
55+
}
56+
57+
class SortFactory {
58+
static getSortAlgo(type: SortType): SortAlgo {
59+
switch (type) {
60+
case SortType.BubbleSort:
61+
return new BubbleSort()
62+
case SortType.InsertSort:
63+
return new InsertSort()
64+
default:
65+
throw new Error('unknown sort algorithm type')
66+
}
67+
}
68+
}
69+
70+
const insertSort = SortFactory.getSortAlgo(SortType.InsertSort)
71+
const test1 = [1, 0, 2, 4, 8, 5, 10]
72+
insertSort.sort(test1)
73+
console.log(test1)
74+
75+

0 commit comments

Comments
 (0)