Skip to content

Commit 458c7ab

Browse files
committed
feat: 添加基础数据结构 二叉树
1 parent 7c78e9a commit 458c7ab

File tree

8 files changed

+215
-10
lines changed

8 files changed

+215
-10
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"PAHNAPLSIIGYIR",
3232
"PAYPALISHIRING",
3333
"PINALSIGYAHRPI",
34+
"postorder",
3435
"powx",
3536
"preorder",
3637
"Prinme",

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ TypeScript / JavaScript 基础算法、数据结构练习,包含 LeetCode 或
2727

2828
## 基础数据结构
2929

30+
- [二叉树深度优先遍历|前序遍历|中序遍历|后序遍历](src/tree/dfs.ts)
31+
- [二叉树广度优先遍历|层序遍历](src/tree/bfs.ts)
32+
3033
## 算法题
3134

3235
### 字符串

src/list/reverse-linked-list.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44

55
import ListNode from "../lib/ListNode"
66

7-
87
export function reverseList (head: ListNode | null): ListNode | null {
9-
let pre = null
10-
let cur = head
11-
while (cur !== null) {
12-
let next = cur.next
13-
cur.next = pre
14-
pre = cur
15-
cur = next
8+
let first = null
9+
let second = head
10+
while (second !== null) {
11+
let third = second.next
12+
second.next = first
13+
first = second
14+
second = third
1615
}
17-
18-
return pre
16+
return first
1917
}

src/tree/TreeNode.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export class TreeNode {
2+
val: number
3+
left: TreeNode | null
4+
right: TreeNode | null
5+
constructor (val?: number, left?: TreeNode | null, right?: TreeNode | null) {
6+
this.val = (val === undefined ? 0 : val)
7+
this.left = (left === undefined ? null : left)
8+
this.right = (right === undefined ? null : right)
9+
}
10+
}

src/tree/bfs.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { TreeNode } from "./TreeNode"
2+
3+
export const bfs = (node: TreeNode): number[] => {
4+
const res = []
5+
const queue = [] // 队列
6+
queue.push(node)
7+
while (queue.length > 0) {
8+
node = queue.shift() as TreeNode // 逻辑上此处一定存在值
9+
res.push(node.val)
10+
11+
if (node.left) {
12+
queue.push(node.left)
13+
}
14+
15+
if (node.right) {
16+
queue.push(node.right)
17+
}
18+
}
19+
return res
20+
}

src/tree/dfs.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { TreeNode } from "./TreeNode"
2+
3+
// const printTree = (node) => {
4+
// if (node === null) return
5+
// console.log(node.val)
6+
// printTree(node.left)
7+
// printTree(node.right)
8+
// }
9+
// 前序遍历递归法
10+
export const preorder = (node: TreeNode | null): number[] => {
11+
if (node === null) return []
12+
return [node.val, ...preorder(node.left), ...preorder(node.right)]
13+
}
14+
15+
// 中序遍历递归法
16+
export const inorder = (node: TreeNode | null): number[] => {
17+
if (node === null) return []
18+
return [...inorder(node.left), node.val, ...inorder(node.right)]
19+
}
20+
21+
// 后序遍历递归法
22+
export const postorder = (node: TreeNode | null): number[] => {
23+
if (node === null) return []
24+
return [...postorder(node.left), ...postorder(node.right), node.val]
25+
}
26+
27+
// 前序遍历循环法
28+
export const preorderCycle = (node: TreeNode | null): number[] => {
29+
const res = []
30+
const stack = []
31+
stack.push(node)
32+
while (stack.length > 0) {
33+
node = stack.pop() as TreeNode
34+
res.push(node.val)
35+
36+
if (node?.right) {
37+
stack.push(node.right)
38+
}
39+
40+
if (node?.left) {
41+
stack.push(node.left)
42+
}
43+
}
44+
return res
45+
}
46+
47+
// 中序遍历循环法
48+
export const inorderCycle = (node: TreeNode | null): number[] => {
49+
const res: number[] = []
50+
const stack = []
51+
while (node !== null || stack.length) {
52+
if (node !== null) {
53+
stack.push(node)
54+
node = node.left
55+
} else {
56+
node = stack.pop() as TreeNode
57+
res.push(node.val)
58+
59+
node = node.right
60+
}
61+
62+
}
63+
return res
64+
}
65+
66+
// 后序遍历循环法
67+
export const postorderCycle = (node: TreeNode | null): number[] => {
68+
const res = []
69+
const stack = []
70+
stack.push(node)
71+
while (stack.length > 0) {
72+
node = stack.pop() as TreeNode
73+
res.unshift(node.val)
74+
75+
if (node?.left) {
76+
stack.push(node.left)
77+
}
78+
79+
if (node?.right) {
80+
stack.push(node.right)
81+
}
82+
}
83+
return res
84+
}

test/tree/bfs.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { bfs } from '../../src/tree/bfs'
2+
import { TreeNode } from '../../src/tree/TreeNode'
3+
4+
// * 为了方便查看整个Tree的定义方式。建议通过常规方法创建整棵树
5+
const tree: TreeNode = {
6+
val: 1,
7+
left: {
8+
val: 2,
9+
left: {
10+
val: 4,
11+
left: null,
12+
right: null
13+
},
14+
right: {
15+
val: 5,
16+
left: null,
17+
right: null
18+
}
19+
},
20+
right: {
21+
val: 3,
22+
left: {
23+
val: 6,
24+
left: null,
25+
right: null
26+
},
27+
right: null
28+
}
29+
}
30+
31+
test('二叉树广度优先遍历', () => {
32+
expect(bfs(tree)).toEqual([1, 2, 3, 4, 5, 6])
33+
})

test/tree/dfs.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { preorderCycle, inorderCycle, postorderCycle } from './../../src/tree/dfs'
2+
import { preorder, inorder, postorder } from '../../src/tree/dfs'
3+
import { TreeNode } from '../../src/tree/TreeNode'
4+
5+
// * 为了方便查看整个Tree的定义方式。建议通过常规方法创建整棵树
6+
const tree: TreeNode = {
7+
val: 1,
8+
left: {
9+
val: 2,
10+
left: {
11+
val: 4,
12+
left: null,
13+
right: null
14+
},
15+
right: {
16+
val: 5,
17+
left: null,
18+
right: null
19+
}
20+
},
21+
right: {
22+
val: 3,
23+
left: {
24+
val: 6,
25+
left: null,
26+
right: null
27+
},
28+
right: null
29+
}
30+
}
31+
32+
describe('二叉树深度优先遍历', () => {
33+
test('前序遍历递归', () => {
34+
expect(preorder(tree)).toEqual([1, 2, 4, 5, 3, 6])
35+
})
36+
37+
test('中序遍历递归', () => {
38+
expect(inorder(tree)).toEqual([4, 2, 5, 1, 6, 3])
39+
})
40+
41+
test('后序遍历递归', () => {
42+
expect(postorder(tree)).toEqual([4, 5, 2, 6, 3, 1])
43+
})
44+
45+
test('前序遍历循环法', () => {
46+
expect(preorderCycle(tree)).toEqual([1, 2, 4, 5, 3, 6])
47+
})
48+
49+
test('中序遍历循环法', () => {
50+
expect(inorderCycle(tree)).toEqual([4, 2, 5, 1, 6, 3])
51+
})
52+
53+
test('后序遍历循环法', () => {
54+
expect(postorderCycle(tree)).toEqual([4, 5, 2, 6, 3, 1])
55+
})
56+
})

0 commit comments

Comments
 (0)