Skip to content

Commit e99488c

Browse files
committed
GLM-5
1 parent 054765e commit e99488c

File tree

10 files changed

+4468
-0
lines changed

10 files changed

+4468
-0
lines changed

001game/algorithms/backtracking.js

Lines changed: 555 additions & 0 deletions
Large diffs are not rendered by default.

001game/algorithms/cipher.js

Lines changed: 451 additions & 0 deletions
Large diffs are not rendered by default.

001game/algorithms/dynamic-programming.js

Lines changed: 465 additions & 0 deletions
Large diffs are not rendered by default.

001game/algorithms/graph.js

Lines changed: 405 additions & 0 deletions
Large diffs are not rendered by default.

001game/algorithms/math.js

Lines changed: 430 additions & 0 deletions
Large diffs are not rendered by default.

001game/algorithms/searching.js

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
const SearchingAlgorithms = [
2+
{
3+
id: 'linear-search',
4+
name: '线性搜索',
5+
description: '线性搜索从数组的第一个元素开始,逐个检查每个元素,直到找到目标值或遍历完整个数组。',
6+
timeComplexity: 'O(n)',
7+
spaceComplexity: 'O(1)',
8+
difficulty: 1,
9+
init: function() {
10+
this.array = generateRandomArray(10, 50);
11+
this.target = this.array[Math.floor(Math.random() * this.array.length)];
12+
createArrayDisplay(this.array);
13+
document.getElementById('step-info').textContent = `查找目标: ${this.target}`;
14+
},
15+
run: function() {
16+
const arr = this.array;
17+
const target = this.target;
18+
19+
for (let i = 0; i < arr.length; i++) {
20+
GameState.animationSteps.push({
21+
type: 'custom',
22+
action: () => {
23+
const items = document.querySelectorAll('.array-item');
24+
items.forEach(item => item.classList.remove('highlight', 'searching', 'found'));
25+
items[i].classList.add('searching');
26+
document.getElementById('step-info').textContent = `检查位置 ${i}: ${arr[i]} ${arr[i] === target ? '= 目标!' : '≠ 目标'}`;
27+
}
28+
});
29+
30+
if (arr[i] === target) {
31+
GameState.animationSteps.push({
32+
type: 'custom',
33+
action: () => {
34+
const items = document.querySelectorAll('.array-item');
35+
items[i].classList.remove('searching');
36+
items[i].classList.add('found');
37+
document.getElementById('step-info').textContent = `找到目标 ${target} 在位置 ${i}!`;
38+
}
39+
});
40+
break;
41+
}
42+
}
43+
44+
runAnimation();
45+
},
46+
challenge: {
47+
question: '线性搜索最坏情况下需要比较多少次?',
48+
options: ['1次', 'n/2次', 'n次', 'log n次'],
49+
correct: 2
50+
}
51+
},
52+
{
53+
id: 'binary-search',
54+
name: '二分搜索',
55+
description: '二分搜索在有序数组中查找目标值,每次将搜索范围缩小一半。',
56+
timeComplexity: 'O(log n)',
57+
spaceComplexity: 'O(1)',
58+
difficulty: 1,
59+
init: function() {
60+
this.array = Array.from({ length: 15 }, (_, i) => (i + 1) * 3);
61+
this.target = this.array[Math.floor(Math.random() * this.array.length)];
62+
createArrayDisplay(this.array);
63+
document.getElementById('step-info').textContent = `查找目标: ${this.target}`;
64+
},
65+
run: function() {
66+
const arr = this.array;
67+
const target = this.target;
68+
let left = 0, right = arr.length - 1;
69+
70+
while (left <= right) {
71+
const mid = Math.floor((left + right) / 2);
72+
73+
GameState.animationSteps.push({
74+
type: 'custom',
75+
action: () => {
76+
const items = document.querySelectorAll('.array-item');
77+
items.forEach(item => item.classList.remove('highlight', 'searching', 'found'));
78+
for (let i = left; i <= right; i++) {
79+
items[i].classList.add('highlight');
80+
}
81+
items[mid].classList.remove('highlight');
82+
items[mid].classList.add('searching');
83+
document.getElementById('step-info').textContent =
84+
`搜索范围: [${left}, ${right}], 中间位置: ${mid}, 值: ${arr[mid]}`;
85+
}
86+
});
87+
88+
if (arr[mid] === target) {
89+
GameState.animationSteps.push({
90+
type: 'custom',
91+
action: () => {
92+
const items = document.querySelectorAll('.array-item');
93+
items.forEach(item => item.classList.remove('highlight', 'searching'));
94+
items[mid].classList.add('found');
95+
document.getElementById('step-info').textContent = `找到目标 ${target} 在位置 ${mid}!`;
96+
}
97+
});
98+
break;
99+
} else if (arr[mid] < target) {
100+
GameState.animationSteps.push({
101+
type: 'custom',
102+
action: () => {
103+
document.getElementById('step-info').textContent =
104+
`${arr[mid]} < ${target}, 在右半部分继续搜索`;
105+
}
106+
});
107+
left = mid + 1;
108+
} else {
109+
GameState.animationSteps.push({
110+
type: 'custom',
111+
action: () => {
112+
document.getElementById('step-info').textContent =
113+
`${arr[mid]} > ${target}, 在左半部分继续搜索`;
114+
}
115+
});
116+
right = mid - 1;
117+
}
118+
}
119+
120+
runAnimation();
121+
},
122+
challenge: {
123+
question: '二分搜索的前提条件是什么?',
124+
options: ['数组必须有序', '数组长度为偶数', '数组元素唯一', '数组元素为整数'],
125+
correct: 0
126+
}
127+
},
128+
{
129+
id: 'jump-search',
130+
name: '跳跃搜索',
131+
description: '跳跃搜索在有序数组中按固定步长跳跃查找,找到范围后再进行线性搜索。',
132+
timeComplexity: 'O(√n)',
133+
spaceComplexity: 'O(1)',
134+
difficulty: 2,
135+
init: function() {
136+
this.array = Array.from({ length: 20 }, (_, i) => (i + 1) * 2);
137+
this.target = this.array[Math.floor(Math.random() * this.array.length)];
138+
createArrayDisplay(this.array);
139+
document.getElementById('step-info').textContent = `查找目标: ${this.target}`;
140+
},
141+
run: function() {
142+
const arr = this.array;
143+
const target = this.target;
144+
const n = arr.length;
145+
const step = Math.floor(Math.sqrt(n));
146+
let prev = 0;
147+
let curr = step;
148+
149+
while (curr < n && arr[curr] < target) {
150+
GameState.animationSteps.push({
151+
type: 'custom',
152+
action: () => {
153+
const items = document.querySelectorAll('.array-item');
154+
items.forEach(item => item.classList.remove('highlight', 'searching'));
155+
items[curr].classList.add('searching');
156+
document.getElementById('step-info').textContent =
157+
`跳跃到位置 ${curr}: ${arr[curr]} < ${target}, 继续跳跃`;
158+
}
159+
});
160+
prev = curr;
161+
curr += step;
162+
}
163+
164+
GameState.animationSteps.push({
165+
type: 'custom',
166+
action: () => {
167+
document.getElementById('step-info').textContent =
168+
`目标可能在范围 [${prev}, ${Math.min(curr, n - 1)}] 内,开始线性搜索`;
169+
}
170+
});
171+
172+
for (let i = prev; i < Math.min(curr, n); i++) {
173+
GameState.animationSteps.push({
174+
type: 'custom',
175+
action: () => {
176+
const items = document.querySelectorAll('.array-item');
177+
items.forEach(item => item.classList.remove('searching'));
178+
items[i].classList.add('searching');
179+
document.getElementById('step-info').textContent =
180+
`检查位置 ${i}: ${arr[i]}`;
181+
}
182+
});
183+
184+
if (arr[i] === target) {
185+
GameState.animationSteps.push({
186+
type: 'custom',
187+
action: () => {
188+
const items = document.querySelectorAll('.array-item');
189+
items[i].classList.remove('searching');
190+
items[i].classList.add('found');
191+
document.getElementById('step-info').textContent =
192+
`找到目标 ${target} 在位置 ${i}!`;
193+
}
194+
});
195+
break;
196+
}
197+
}
198+
199+
runAnimation();
200+
},
201+
challenge: {
202+
question: '跳跃搜索的最优步长是多少?',
203+
options: ['n/2', '√n', 'log n', 'n/4'],
204+
correct: 1
205+
}
206+
},
207+
{
208+
id: 'interpolation-search',
209+
name: '插值搜索',
210+
description: '插值搜索是二分搜索的改进版,根据目标值的大小估计其位置,适用于均匀分布的数据。',
211+
timeComplexity: 'O(log log n)',
212+
spaceComplexity: 'O(1)',
213+
difficulty: 2,
214+
init: function() {
215+
this.array = Array.from({ length: 20 }, (_, i) => (i + 1) * 5);
216+
this.target = this.array[Math.floor(Math.random() * this.array.length)];
217+
createArrayDisplay(this.array);
218+
document.getElementById('step-info').textContent = `查找目标: ${this.target}`;
219+
},
220+
run: function() {
221+
const arr = this.array;
222+
const target = this.target;
223+
let left = 0, right = arr.length - 1;
224+
225+
while (left <= right && target >= arr[left] && target <= arr[right]) {
226+
const pos = left + Math.floor(
227+
((target - arr[left]) * (right - left)) / (arr[right] - arr[left])
228+
);
229+
230+
GameState.animationSteps.push({
231+
type: 'custom',
232+
action: () => {
233+
const items = document.querySelectorAll('.array-item');
234+
items.forEach(item => item.classList.remove('highlight', 'searching', 'found'));
235+
for (let i = left; i <= right; i++) {
236+
items[i].classList.add('highlight');
237+
}
238+
items[pos].classList.remove('highlight');
239+
items[pos].classList.add('searching');
240+
document.getElementById('step-info').textContent =
241+
`插值估计位置: ${pos}, 值: ${arr[pos]}`;
242+
}
243+
});
244+
245+
if (arr[pos] === target) {
246+
GameState.animationSteps.push({
247+
type: 'custom',
248+
action: () => {
249+
const items = document.querySelectorAll('.array-item');
250+
items.forEach(item => item.classList.remove('highlight', 'searching'));
251+
items[pos].classList.add('found');
252+
document.getElementById('step-info').textContent =
253+
`找到目标 ${target} 在位置 ${pos}!`;
254+
}
255+
});
256+
break;
257+
}
258+
259+
if (arr[pos] < target) {
260+
left = pos + 1;
261+
} else {
262+
right = pos - 1;
263+
}
264+
}
265+
266+
runAnimation();
267+
},
268+
challenge: {
269+
question: '插值搜索在什么情况下性能最好?',
270+
options: ['数据随机分布', '数据均匀分布', '数据完全逆序', '数据有重复'],
271+
correct: 1
272+
}
273+
}
274+
];

0 commit comments

Comments
 (0)