Skip to content

Commit fae2556

Browse files
committed
[Feature] add for new
1 parent 13bbcd8 commit fae2556

File tree

5 files changed

+672
-0
lines changed

5 files changed

+672
-0
lines changed

T192-sort-bubble-sort.html

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<!DOCTYPE html>
2+
<html lang="zh">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>T192 冒泡排序可视化</title>
6+
<style>
7+
body {
8+
font-family: sans-serif;
9+
padding: 20px;
10+
background: #f0f0f0;
11+
}
12+
.controls {
13+
margin-bottom: 20px;
14+
}
15+
#visual {
16+
display: flex;
17+
align-items: flex-end;
18+
height: 300px;
19+
margin-bottom: 20px;
20+
gap: 5px;
21+
}
22+
.bar {
23+
width: 30px;
24+
background-color: #4caf50;
25+
text-align: center;
26+
color: white;
27+
transition: height 0.3s ease, background-color 0.3s ease;
28+
}
29+
.bar.active {
30+
background-color: orange !important;
31+
}
32+
.bar.sorted {
33+
background-color: gray !important;
34+
}
35+
#log {
36+
background-color: #111;
37+
color: #0f0;
38+
padding: 10px;
39+
height: 200px;
40+
overflow-y: auto;
41+
font-family: monospace;
42+
white-space: pre-wrap;
43+
}
44+
input[type="text"], input[type="number"] {
45+
padding: 5px;
46+
width: 300px;
47+
margin-bottom: 10px;
48+
}
49+
button {
50+
padding: 8px 16px;
51+
font-size: 16px;
52+
}
53+
a {
54+
display: inline-block;
55+
margin-top: 20px;
56+
}
57+
</style>
58+
</head>
59+
<body>
60+
61+
<h2>🌀 T192 冒泡排序可视化</h2>
62+
63+
<div class="controls">
64+
输入数组(用逗号分隔):<br>
65+
<input type="text" id="inputArray" value="5,1,4,2,8"><br>
66+
动画间隔(毫秒):<input type="number" id="interval" value="1000" min="100" max="5000"><br>
67+
<button onclick="startSort()">可视化排序</button>
68+
</div>
69+
70+
<div id="visual"></div>
71+
72+
<div id="log"></div>
73+
74+
<a href="index.html">← 返回首页</a>
75+
76+
<script>
77+
let bars = [];
78+
79+
function log(msg) {
80+
const logBox = document.getElementById('log');
81+
logBox.innerText += msg + "\n";
82+
logBox.scrollTop = logBox.scrollHeight;
83+
}
84+
85+
function render(array, highlight = [], sorted = []) {
86+
const container = document.getElementById('visual');
87+
container.innerHTML = '';
88+
const maxVal = Math.max(...array);
89+
bars = [];
90+
91+
array.forEach((val, idx) => {
92+
const bar = document.createElement('div');
93+
bar.classList.add('bar');
94+
if (highlight.includes(idx)) bar.classList.add('active');
95+
if (sorted.includes(idx)) bar.classList.add('sorted');
96+
bar.style.height = `${(val / maxVal) * 100 + 50}px`;
97+
bar.innerText = val;
98+
container.appendChild(bar);
99+
bars.push(bar);
100+
});
101+
}
102+
103+
async function bubbleSortVisual(arr, delay) {
104+
const len = arr.length;
105+
for (let i = 0; i < len; i++) {
106+
let swapped = false;
107+
for (let j = 0; j < len - 1 - i; j++) {
108+
render(arr, [j, j + 1]);
109+
log(`比较 nums[${j}]=${arr[j]} 和 nums[${j+1}]=${arr[j+1]}`);
110+
await new Promise(r => setTimeout(r, delay));
111+
112+
if (arr[j] > arr[j + 1]) {
113+
log(`交换 nums[${j}] 和 nums[${j+1}]:${arr[j]} > ${arr[j+1]}`);
114+
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
115+
swapped = true;
116+
render(arr, [j, j + 1]);
117+
await new Promise(r => setTimeout(r, delay));
118+
}
119+
}
120+
121+
log(`第 ${i + 1} 轮结束:${arr.join(', ')}`);
122+
if (!swapped) {
123+
log('没有发生交换,提前结束排序。');
124+
break;
125+
}
126+
}
127+
render(arr, [], Array.from(arr.keys())); // 标记全部为 sorted
128+
log(`✅ 排序完成:${arr.join(', ')}`);
129+
}
130+
131+
function startSort() {
132+
const input = document.getElementById('inputArray').value;
133+
const interval = parseInt(document.getElementById('interval').value) || 1000;
134+
const arr = input.split(',').map(x => parseInt(x.trim())).filter(x => !isNaN(x));
135+
if (arr.length === 0) {
136+
alert("请输入有效的数组");
137+
return;
138+
}
139+
140+
document.getElementById('log').innerText = '';
141+
log(`开始排序:${arr.join(', ')}`);
142+
render(arr);
143+
bubbleSortVisual(arr, interval);
144+
}
145+
</script>
146+
</body>
147+
</html>
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<!DOCTYPE html>
2+
<html lang="zh">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>T192 插入排序可视化</title>
6+
<style>
7+
body {
8+
font-family: Arial, sans-serif;
9+
margin: 20px;
10+
}
11+
12+
#sortView, #searchView {
13+
display: flex;
14+
align-items: flex-end;
15+
height: 200px;
16+
margin-bottom: 10px;
17+
border: 1px solid #ccc;
18+
padding: 10px;
19+
position: relative;
20+
}
21+
22+
.bar {
23+
width: 30px;
24+
margin: 0 5px;
25+
background-color: steelblue;
26+
text-align: center;
27+
color: white;
28+
transition: all 0.3s ease;
29+
position: relative;
30+
}
31+
32+
.highlight {
33+
background-color: orange !important;
34+
}
35+
36+
.insert {
37+
background-color: green !important;
38+
}
39+
40+
.pointer {
41+
position: absolute;
42+
bottom: -20px;
43+
width: 100%;
44+
text-align: center;
45+
font-weight: bold;
46+
color: red;
47+
}
48+
49+
#log {
50+
background-color: black;
51+
color: white;
52+
padding: 10px;
53+
height: 200px;
54+
overflow-y: auto;
55+
font-family: monospace;
56+
white-space: pre-wrap;
57+
margin-top: 10px;
58+
}
59+
60+
input, button {
61+
margin: 5px;
62+
}
63+
64+
a {
65+
display: inline-block;
66+
margin-top: 20px;
67+
}
68+
69+
h3 {
70+
margin-bottom: 5px;
71+
}
72+
</style>
73+
</head>
74+
<body>
75+
76+
<h2>T192 插入排序(带二分查找)可视化</h2>
77+
78+
<label>输入数组(用逗号分隔):</label>
79+
<input type="text" id="inputArray" value="5,3,1,4,6,2,7" />
80+
<br>
81+
<label>动画间隔(ms):</label>
82+
<input type="number" id="interval" value="1000" />
83+
<button onclick="startVisualization()">🔍 开始可视化</button>
84+
85+
<h3>排序直方图</h3>
86+
<div id="sortView"></div>
87+
88+
<h3>当前二分查找过程</h3>
89+
<div id="searchView"></div>
90+
91+
<h3>日志输出</h3>
92+
<div id="log"></div>
93+
94+
<a href="index.html">🔙 返回首页</a>
95+
96+
<script>
97+
function log(msg) {
98+
const logDiv = document.getElementById("log");
99+
logDiv.innerText += msg + "\n";
100+
logDiv.scrollTop = logDiv.scrollHeight;
101+
}
102+
103+
function sleep(ms) {
104+
return new Promise(resolve => setTimeout(resolve, ms));
105+
}
106+
107+
function renderSortView(arr, highlight = [], insertIdx = -1) {
108+
const container = document.getElementById("sortView");
109+
container.innerHTML = "";
110+
const max = Math.max(...arr);
111+
arr.forEach((val, i) => {
112+
const bar = document.createElement("div");
113+
bar.className = "bar";
114+
bar.style.height = `${(val / max) * 100 + 50}px`;
115+
bar.innerText = val;
116+
if (highlight.includes(i)) bar.classList.add("highlight");
117+
if (i === insertIdx) bar.classList.add("insert");
118+
container.appendChild(bar);
119+
});
120+
}
121+
122+
function renderSearchView(arr, left, right, mid) {
123+
const container = document.getElementById("searchView");
124+
container.innerHTML = "";
125+
arr.forEach((val, i) => {
126+
const bar = document.createElement("div");
127+
bar.className = "bar";
128+
bar.style.height = "40px";
129+
bar.style.backgroundColor = "#666";
130+
bar.innerText = val;
131+
132+
if (i === mid) bar.classList.add("highlight");
133+
else if (i === left || i === right) bar.classList.add("insert");
134+
135+
// 添加 L/M/R 指针
136+
const pointer = document.createElement("div");
137+
pointer.className = "pointer";
138+
if (i === left) pointer.innerText = "L";
139+
if (i === right) pointer.innerText += "R";
140+
if (i === mid) pointer.innerText += "M";
141+
bar.appendChild(pointer);
142+
143+
container.appendChild(bar);
144+
});
145+
}
146+
147+
async function binarySearchVisual(nums, left, right, target, delay) {
148+
log(`🔍 二分查找:target=${target},初始区间=[${left}, ${right}]`);
149+
while (left <= right) {
150+
const mid = left + Math.floor((right - left) / 2);
151+
log(` → mid=${mid}, nums[mid]=${nums[mid]}`);
152+
renderSearchView(nums, left, right, mid);
153+
await sleep(delay);
154+
155+
if (nums[mid] < target) {
156+
left = mid + 1;
157+
} else {
158+
right = mid - 1;
159+
}
160+
}
161+
log(`✅ 插入位置:${left}\n`);
162+
return left;
163+
}
164+
165+
async function insertionSortVisual(arr, delay) {
166+
renderSortView(arr);
167+
for (let i = 1; i < arr.length; i++) {
168+
const curNum = arr[i];
169+
log(`=== 第 ${i} 步:当前数 = ${curNum} ===`);
170+
const insertPos = await binarySearchVisual(arr.slice(0, i), 0, i - 1, curNum, delay);
171+
172+
// 元素右移
173+
for (let j = i; j > insertPos; j--) {
174+
arr[j] = arr[j - 1];
175+
}
176+
arr[insertPos] = curNum;
177+
178+
log(`💡 插入 ${curNum} 到位置 ${insertPos}`);
179+
renderSortView(arr, [], insertPos);
180+
await sleep(delay);
181+
}
182+
183+
renderSearchView([], -1, -1, -1); // 清空二分查找区域
184+
log("\n🎉 排序完成!");
185+
renderSortView(arr);
186+
}
187+
188+
function startVisualization() {
189+
document.getElementById("log").innerText = "";
190+
const input = document.getElementById("inputArray").value;
191+
const arr = input.split(",").map(x => parseInt(x.trim()));
192+
const delay = parseInt(document.getElementById("interval").value);
193+
insertionSortVisual([...arr], delay);
194+
}
195+
</script>
196+
197+
</body>
198+
</html>

0 commit comments

Comments
 (0)