news 2026/9/1 6:38:47

用HTML+CSS+JavaScript做冒泡排序可视化,24个数字动画演示

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用HTML+CSS+JavaScript做冒泡排序可视化,24个数字动画演示

初学排序算法时,很多人都有过这样的体验:冒泡排序的代码不长,逻辑看起来也直白,可真要在脑子里模拟 24 个无序数字每轮交换后的样子,很快就跟不上了。外层循环进入第 3 轮时,数组的哪些区域已经稳定?内层循环比较到哪一位就可以停下来?如果某一轮一个交换都没发生,是不是说明整个数组已经有序?这些问题如果只看代码,回答起来并不轻松。

如果能把排序过程变成可视化的动画,这些疑问会清晰得多。本文就用纯 HTML + CSS + JavaScript 实现一个 24 个数字的冒泡排序可视化页面,整个页面不依赖任何框架和构建工具,保存成一个 HTML 文件后,浏览器双击就能运行。在动画里,你会清楚地看到每一轮比较发生在哪两个数字之间,哪些数字正在交换,哪些数字已经排好并进入绿色区域,以及理论上最多 276 次比较是如何一步步完成的。

1. 冒泡排序:一个“老牌但值得细看”的排序算法

1.1 冒泡排序的基本思想

冒泡排序(Bubble Sort)的核心思想是反复比较相邻的两个元素,如果顺序不符合要求,就把它们交换。以升序排序为例:

  1. 从数组的第一个元素开始,依次比较arr[j]arr[j + 1]
  2. 如果arr[j] > arr[j + 1],说明前一个数字比后一个大,交换它们。
  3. 继续移动到下一对相邻元素,重复上述比较与交换。
  4. 当一轮比较结束后,数组末尾一定是当前范围内最大的元素。
  5. 下一轮比较时,忽略已经排到末尾的元素,重复整个过程。

“冒泡”这个名字很形象:较小的数字会像气泡一样逐渐往前移动,较大的数字则会一层层“沉”到末尾。以数组[5, 1, 4, 2]为例,第一轮比较结束后,最大值 5 会被交换到索引3的位置,之后 5 就不再参与后续比较。

从算法性质来看,冒泡排序有以下几个关键点:

  • 时间复杂度:最坏情况和平均情况都是O(n^2);如果数组已经有序,并且代码加入了提前退出机制,最好情况可以优化到O(n)
  • 空间复杂度O(1),它只需要一个临时变量用来交换元素,属于原地排序。
  • 稳定性:相邻元素只有在前一个大于后一个时才交换,相等元素不会交换相对顺序,因此冒泡排序是稳定排序。

1.2 为什么要把冒泡排序“可视化”

学习排序算法时,大部分人都会经历三个阶段:能看懂代码、能手动模拟、能根据场景选择算法。手动模拟是很多人卡住的一步,因为数据一旦多起来,大脑的工作记忆会很快被占满。

可视化最大的价值在于把时间维度拉进画面。你不再只是看到代码在反复跑循环,而是能直观看到:

  • 黄色指针在相邻元素之间移动,代表正在进行比较;
  • 红色闪烁的两个柱子代表正在发生交换;
  • 绿色区域从右往左逐渐变长,代表已排序部分不断增加;
  • 如果某一轮完全没有发生交换,动画可以提前结束,而不是继续傻跑。

很多同学在面试前临时背规范排序算法,却很难说出优化点在哪里。通过可视化理解冒泡排序的“提前退出”和“有序区边界”之后,这些细节会变成图形记忆,比死记硬背牢固得多。

1.3 为什么用 24 个数字来演示

24 是一个非常合适的可视化规模。

如果是 5 个数字,排序过程太短,还没来得及看清就结束了;如果是 1000 个数字,柱状图会被压缩得看不出细节,动画时间也会变得太长。24 个数字既有足够的排列组合空间,又能在普通屏幕上一根根清楚地展示。

从计算量来看,24 个数字最坏情况下需要比较:

23 + 22 + 21 + ... + 1 = 276 次

如果在每一步之间等待约 80ms,整体动画过程大概需要二十多秒,这个时长对理解算法来说非常合适。你也可以通过速度滑块将其压缩到几秒,或者放慢到半分钟,观察每个细节。

2. 环境准备:只需要一个浏览器

2.1 为什么选择原生 Web 技术

排序可视化可以通过多种方案实现:命令行输出、Python matplotlib 动画、Java Swing、JavaScript Canvas 等。本文选择HTML + CSS + JavaScript,原因很实际:

  • 零安装:任何有浏览器的电脑都能运行,不需要安装 Python、JDK 或任何包管理器。
  • 跨平台:Windows、macOS、Linux 都能直接打开。
  • 交互自然:按钮、滑块、暂停/继续功能用浏览器原生控件就能实现。
  • 绘图高效:Canvas 2D 在 Web 端绘制几百根柱子非常流畅。

算法逻辑本身和语言无关,JavaScript 写的冒泡排序和其他语言并没有本质区别。如果你熟悉 C++ 或 Java,下面的实现依然很容易看懂。

2.2 目录结构与运行方式

整个项目只需要一个文件,例如bubble-sort-visualize.html。项目结构如下:

bubble-sort-visualize/ └── bubble-sort-visualize.html # 完整可视化页面

运行方式有两种:

  1. 直接双击 HTML 文件,用浏览器打开。
  2. 在当前目录启动一个静态服务器,例如python -m http.server 8080,然后访问http://localhost:8080

后续代码都会围绕这一个文件展开。

3. 先用 JavaScript 实现冒泡排序核心逻辑

3.1 基础版冒泡排序

先看最标准的冒泡排序写法,这里用 JavaScript 来实现:

// 文件路径:src/bubbleSort.js function bubbleSort(arr) { const n = arr.length; for (let i = 0; i < n - 1; i++) { for (let j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { // 交换相邻元素 [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; } } } return arr; } const data = [64, 34, 25, 12, 22, 11, 90]; console.log(bubbleSort(data)); // 输出:[11, 12, 22, 25, 34, 64, 90]

代码中的[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]是 ES6 的解构赋值交换技巧,等价于:

let temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp;

外层循环控制“总共需要跑多少轮”,内层循环控制“当前轮需要比较到哪个位置”。因为每跑完一轮,末尾就会多一个排好的元素,所以内层循环上限是n - 1 - i

3.2 优化一:提前退出

如果原数组已经基本有序,基础版依然会老老实实跑完所有外层循环,造成大量无效比较。加入一个swapped标志,就可以在某一轮完全没有交换时提前结束:

function bubbleSortOptimized(arr) { const n = arr.length; for (let i = 0; i < n - 1; i++) { let swapped = false; for (let j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; swapped = true; } } // 如果这一轮没有发生任何交换,说明数组已经有序 if (!swapped) { break; } } return arr; }

在最好情况下,也就是数组已经有序时,这个版本只需要执行一轮比较,比较n - 1次,时间复杂度降到O(n)。可视化页面中,每当一轮没有发生交换,动画也会立即停止,用户能直观看到“提前退出”的意义。

3.3 优化二:记录最后一次交换位置

第二个优化思路是缩短下一轮的有序区边界。理论上,如果最后一对交换发生在jj + 1之间,那么索引j + 1之后的所有元素已经在正确位置上,下一轮只需要比较到j + 1位置即可。

function bubbleSortBoundary(arr) { let n = arr.length; while (n > 1) { let lastSwapIndex = 0; for (let j = 0; j < n - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; lastSwapIndex = j + 1; } } // 把下一轮的边界收缩到最后一次交换的位置 n = lastSwapIndex; } return arr; }

这种方式对“前半部分无序、后半部分已经有序”的数组非常友好。虽然本文的可视化页面还是采用“每轮末尾固定扩大一个绿色元素”的方式展示,但你可以在扩展练习中尝试把这种优化也做进动画,观察边界是如何一步步收缩的。

如果大家习惯 C++,可以对比一下同样的逻辑:

// 文件路径:bubbleSort.cpp void bubbleSort(vector<int>& arr) { int n = arr.size(); for (int i = 0; i < n - 1; i++) { bool swapped = false; for (int j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { swap(arr[j], arr[j + 1]); swapped = true; } } if (!swapped) break; } }

算法跨语言的核心逻辑是完全一致的,差别只在语法层面。因此,你在 HTML 页面里看到的动画过程,同样适合解释 C++ 或 Java 中的冒泡排序行为。

4. 可视化设计:让 24 个数字“跑”起来

4.1 可视化目标拆解

在写代码之前,先明确这个可视化页面需要满足哪些要求:

  • 柱状图阵列:24 个数字用 24 根柱子表示,柱子的高度代表数字大小。
  • 颜色状态区分:比较中的位置显示黄色,交换中的位置显示红色,已排序区域显示绿色,普通位置显示蓝色。
  • 操作统计:实时显示当前轮次、比较次数、交换次数。
  • 可控制性:支持开始排序、暂停/继续、打乱数组,以及调节动画速度。
  • 防误操作:排序中不允许重复启动,重置数组时能安全中止旧任务。

4.2 使用 Canvas 绘制而不是操作 DOM

有人可能会问:为什么不直接创建 24 个<div>,每次排序时改它的高度和颜色?

用 DOM 当然可以实现,但存在两个问题:

  1. 频繁操作 DOM 开销大。排序每走一步,可能要同时改多个 div 的heightbackground,如果步数达到几百次,页面很容易出现卡顿。
  2. 逻辑分散。颜色、高度、位置都要分别更新,代码可读性差。

Canvas 的做法是每次状态变化后整帧重绘,由clearRect + fillRect完成绘制。24 个柱子的重绘量非常小,性能完全不是问题,而且绘制逻辑集中在一个draw()函数里,数据状态与表现状态天然清晰分离。

4.3 核心难点:让排序过程可暂停、可继续

这是整个可视化页面最容易踩坑的地方。

如果直接调用同步的bubbleSort(),JavaScript 会一口气把排序执行完。由于浏览器的主线程被占住,页面无法重新绘制动画,你只能看到最终结果。这正是很多初学者在写可视化时“动画一闪而过”的根本原因。

解决思路是把排序函数改成异步函数,在每次比较和交换之后,await一个等待操作,把控制权交还给浏览器,让浏览器有机会绘制当前帧。

function sleep(ms) { return new Promise(resolve => { let remaining = ms; const timer = setInterval(() => { if (stopSignal) { clearInterval(timer); resolve(); return; } if (paused) { return; // 暂停状态,不减少 remaining } remaining -= 20; if (remaining <= 0) { clearInterval(timer); resolve(); } }, 20); }); }

在这个sleep实现里,每次等待分成若干个 20ms 的小片段。如果暂停标志pausedtrue,剩余时间不减少,排序就“卡住”了;点击继续后,剩余时间继续减少。如果重置按钮设置了stopSignal,等待会立即结束,后续排序逻辑发现信号后主动退出,避免旧任务继续操作新数组。

4.4 状态字段设计

为了让绘制函数知道当前怎么上色,需要维护以下状态:

状态字段说明
普通状态-默认蓝色
比较中compareIndex黄色,存储[j, j + 1]
交换中swapIndex红色,存储[j, j + 1]
已排序区sortedCount绿色,用于计算已就位的柱子数量
排序标志isSorting防止重复启动
暂停标志paused暂停状态下等待不结束
停止信号stopSignal重置数组时中止排序任务

每次排序循环推进时,更新这些字段,然后调用draw(),页面就会立刻看到最新状态。

5. 完整实战:24 个数字冒泡排序可视化页面

5.1 页面 HTML 结构

页面分为四个区域:标题、画布、统计信息、控制按钮。

<div class="container"> <h2>冒泡排序可视化(24 个数字)</h2> <canvas id="sortCanvas" width="720" height="360"></canvas> <div class="stats"> <span>轮次:<b id="roundIndex">0</b></span> <span>比较次数:<b id="compareCount">0</b></span> <span>交换次数:<b id="swapCount">0</b></span> </div> <div class="controls"> <button id="startBtn">开始排序</button> <button id="pauseBtn" disabled>暂停</button> <button id="resetBtn">打乱数组</button> <label for="speedRange">速度: <input id="speedRange" type="range" min="10" max="300" value="80"> </label> </div> </div>

速度滑块的值单位是毫秒。值越小,动画越快;值越大,动画越慢。默认 80ms,在 24 个数字场景下整体节奏比较适中。

5.2 CSS 样式

样式采用深色背景,重点突出画布区域和状态颜色。

* { box-sizing: border-box; } body { margin: 0; padding: 20px; background: #1e1e2e; font-family: "Microsoft YaHei", "PingFang SC", sans-serif; color: #e0e0e0; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .container { background: #282a36; border-radius: 12px; padding: 24px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); width: fit-content; } h2 { margin: 0 0 16px; font-size: 20px; text-align: center; } canvas { display: block; background: #1e1e28; border-radius: 8px; margin-bottom: 16px; } .stats { display: flex; justify-content: space-around; margin-bottom: 16px; font-size: 14px; } .stats b { color: #f8f8f2; } .controls { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; align-items: center; } button { padding: 8px 18px; font-size: 14px; border: none; border-radius: 6px; background: #6272a4; color: #f8f8f2; cursor: pointer; transition: background 0.2s; } button:hover { background: #7085c0; } button:disabled { opacity: 0.5; cursor: not-allowed; } input[type="range"] { vertical-align: middle; }

5.3 JavaScript 核心代码

首先是全局变量和初始化函数。为了生成不重复的 24 个数字,使用 Fisher-Yates 洗牌算法生成 1 到 24 的随机排列。

const canvas = document.getElementById('sortCanvas'); const ctx = canvas.getContext('2d'); const startBtn = document.getElementById('startBtn'); const pauseBtn = document.getElementById('pauseBtn'); const resetBtn = document.getElementById('resetBtn'); const speedInput = document.getElementById('speedRange'); const roundSpan = document.getElementById('roundIndex'); const compareSpan = document.getElementById('compareCount'); const swapSpan = document.getElementById('swapCount'); const SIZE = 24; let arr = []; let compareIndex = null; let swapIndex = null; let sortedCount = 0; let compareCount = 0; let swapCount = 0; let roundIndex = 0; let isSorting = false; let paused = false; let stopSignal = false; function generateRandomArray(size) { const arr = []; for (let i = 1; i <= size; i++) { arr.push(i); } for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } function updateStats() { roundSpan.textContent = roundIndex; compareSpan.textContent = compareCount; swapSpan.textContent = swapCount; } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); const barWidth = canvas.width / arr.length; const maxValue = Math.max(...arr); for (let i = 0; i < arr.length; i++) { const barHeight = (arr[i] / maxValue) * (canvas.height - 20); const x = i * barWidth; const y = canvas.height - barHeight; let color = '#4a9eff'; if (compareIndex && compareIndex.includes(i)) { color = '#ffc53d'; } if (swapIndex && swapIndex.includes(i)) { color = '#ff4d4f'; } if (i >= arr.length - sortedCount) { color = '#52c41a'; } ctx.fillStyle = color; ctx.fillRect(x + 1, y, barWidth - 2, barHeight); } updateStats(); }

接下来是sleep函数和排序主逻辑。

function sleep(ms) { return new Promise(resolve => { let remaining = ms; const timer = setInterval(() => { if (stopSignal) { clearInterval(timer); resolve(); return; } if (paused) { return; } remaining -= 20; if (remaining <= 0) { clearInterval(timer); resolve(); } }, 20); }); } async function runBubbleSort() { if (isSorting) return; isSorting = true; stopSignal = false; startBtn.disabled = true; pauseBtn.disabled = false; const n = arr.length; for (let i = 0; i < n - 1; i++) { if (stopSignal) break; roundIndex = i + 1; let swapped = false; for (let j = 0; j < n - 1 - i; j++) { if (stopSignal) break; compareIndex = [j, j + 1]; swapIndex = null; draw(); await sleep(speedInput.value); if (stopSignal) return; compareCount++; if (arr[j] > arr[j + 1]) { swapIndex = [j, j + 1]; [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; swapCount++; draw(); await sleep(speedInput.value); if (stopSignal) return; swapped = true; } } sortedCount++; compareIndex = null; swapIndex = null; if (!swapped) break; } if (!stopSignal) { sortedCount = n; draw(); } isSorting = false; startBtn.disabled = false; pauseBtn.disabled = true; pauseBtn.textContent = '暂停'; paused = false; }

最后是按钮事件绑定和初始化。

startBtn.addEventListener('click', runBubbleSort); pauseBtn.addEventListener('click', () => { if (!isSorting) return; paused = !paused; pauseBtn.textContent = paused ? '继续' : '暂停'; }); resetBtn.addEventListener('click', () => { stopSignal = true; init(); }); function init() { isSorting = false; paused = false; stopSignal = false; compareIndex = null; swapIndex = null; sortedCount = 0; compareCount = 0; swapCount = 0; roundIndex = 0; arr = generateRandomArray(SIZE); draw(); startBtn.disabled = false; pauseBtn.disabled = true; pauseBtn.textContent = '暂停'; } init();

5.4 运行效果与关键交互

bubble-sort-visualize.html保存到本地并用浏览器打开,页面会随机生成 24 根蓝色柱子。点击“开始排序”后,你会看到:

  1. 黄色指针从左侧开始,一步一步地在相邻两根柱子之间移动。
  2. 如果黄色指针指向的左侧柱子比右侧高,两根柱子会变红,并在画面中完成一次高度交换。
  3. 每当外层循环完成一轮,右侧就会出现一根绿色柱子,并且逐步向左蔓延。
  4. 如果某一轮没有任何交换,排序会立即停止,此时绿色区域可能尚未覆盖所有柱子,但数组已经有序。
  5. 点击“暂停”可以随时中断动画,再点击“继续”从当前位置恢复。
  6. 点击“打乱数组”会清空排序状态,重新生成一组随机数字。

整个过程中,统计区的“轮次、比较次数、交换次数”会同步刷新。你还能看到实际比较次数往往少于理论最大值的276次,因为提前退出机制会在数组有序后立刻收工。

6. 常见问题与排查思路

在实际开发或调试可视化页面时,比较容易遇到下面几个问题:

问题现象常见原因解决思路
点击开始排序没有反应isSorting一直为true,或按钮事件未绑定检查事件监听是否注册,运行前打印isSorting状态
动画一闪而过,看不到过程排序函数是同步的,主线程被阻塞将排序函数改为async,每次比较和交换后await sleep()
暂停后点击继续,没有恢复sleep函数没有检查paused标志使用setInterval轮询paused状态,暂停期间不减少剩余时间
排序过程中打乱数组,旧任务继续修改数据缺少停止信号添加stopSignal,在sleep和循环中判断并主动退出
多次点击开始按钮,产生多个并发排序任务缺少互斥判断在排序函数开头判断isSorting,为true时直接返回
柱子底部没有对齐或高度越界计算高度时没有考虑画布边距使用canvas.height - 20作为最大高度,留出底部安全距离
绿色已排序区域显示错误sortedCount更新时机不对每一轮外层循环结束后再sortedCount++,最后强制设为n

其中最隐蔽的是第五个问题。如果用户快速双击“开始排序”,异步函数会同时启动多个任务,它们共同修改同一个数组,最终画面的颜色和统计数据都会乱掉。解决办法就是加一把简单的锁:

if (isSorting) return; isSorting = true;

排序结束时再把isSorting置回false。这个思路在很多异步场景里都能复用。

7. 最佳实践与工程建议

7.1 数据、状态与视图分离

整个页面虽然只有一个 HTML 文件,但代码结构上应该划分为三层:

  • 数据层arr数组。
  • 状态层compareIndexswapIndexsortedCountcompareCountswapCountisSortingpausedstopSignal
  • 视图层draw()函数。

draw()只负责根据当前数组和状态绘制画面,不负责修改数组。排序算法只负责修改数组和状态,不需要关心柱子的坐标。这种拆分方式在项目扩大后特别有用,比如以后要加入插入排序可视化,只需要实现新的排序函数,复用同一套draw()

7.2 主动停止信号比强制刷新更安全

很多人在处理“重置按钮”时,会直接调用location.reload()来重载页面。这样虽然简单,但用户体验很差,而且会丢失排序统计信息。更好的做法是设置一个stopSignal,让正在运行的异步函数在下一个安全位置主动退出,然后调用init()重置页面状态。

这种“协作式取消”的思路在异步编程中非常常见,类似前端请求中的取消令牌(CancelToken)概念。

7.3 合理控制动画性能

在 24 个数字的场景下,每帧绘制 24 个矩形,性能完全不是问题。但如果以后要扩展到几百个数字,可以考虑以下优化:

  • draw()中的Math.max(...arr)改为排序前一次性计算,避免每帧扫描整个数组。
  • 使用requestAnimationFrame统一控制绘制频率,避免在极度快速的排序中重复绘制无效帧。
  • 对柱子填充颜色做缓存,减少每次计算状态的开销。

不过对于本文的规模,保持代码简单更重要。

7.4 让排序算法可测试

可视化代码虽然好看,但排序逻辑本身也值得单独验证。实际操作中,可以把bubbleSort抽象成一个纯函数:

function bubbleSort(arr) { const result = [...arr]; // 排序逻辑... return result; }

然后写一段简单的测试代码,验证排序结果和稳定性。这样当可视化页面出现异常时,你能快速确认是算法问题还是渲染问题。

7.5 后续扩展方向

这个可视化页面完成后,可以继续扩展,让它的价值更大:

  1. 增加更多排序算法:选择排序、插入排序、快速排序、归并排序,共用同一套状态管理和绘制逻辑。
  2. 增加单步模式:点击一次按钮,只执行一步比较或交换,适合课堂演示。
  3. 增加序列展示:每一轮结束后的数组状态可以记录到日志区域,方便回放。
  4. 增加逆序度显示:统计当前数组的逆序对数量,观察排序过程中逆序对如何逐步减少。

无论怎么扩展,核心思想不变:让算法过程可见、可交互、可解释

8. 自然收尾的实践建议

冒泡排序在工业级项目中并不是首选算法,因为平均时间复杂度较高

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 6:37:15

深度强化学习智能决策系统:源码架构、部署与调参实战

简介&#xff1a;基于深度强化学习的智能决策系统源码包&#xff0c;面向具备一定深度学习基础的研究者与开发者&#xff0c;可用于游戏AI、机器人控制等需要实时决策的仿真场景。项目以深度Q网络&#xff08;DQN&#xff09;为核心&#xff0c;实现神经网络价值函数估计、经验…

作者头像 李华
网站建设 2026/9/1 6:36:38

GB300 NVL72性能超H200七倍?揭秘机柜级AI算力系统

这两年只要聊到AI算力&#xff0c;几乎绕不开一个话题&#xff1a; GPU 又迭代了。从 A100 到 H100&#xff0c;再到 H200&#xff0c;每一次更新都像在给大模型训练场换发动机。但最近密集出现在讨论里的“英伟达 GB300 NVL72”&#xff0c;不仅仅是一个新的 GPU 型号名&#…

作者头像 李华
网站建设 2026/9/1 6:35:34

圆刚采集卡RECentral实战指南:从驱动安装到直播调参

简介&#xff1a;一套面向圆刚 C985 视频采集卡用户的官方安装程序&#xff0c;内置 RECentral 采集软件&#xff0c;适用于直播推流、屏幕录制、教学演示等多媒体信息采集场景&#xff0c;帮助用户更稳定地完成视频信号捕获与管理。压缩包总计 886 个文件&#xff0c;大小约 8…

作者头像 李华
网站建设 2026/9/1 6:35:15

用ADS谐波平衡仿真搞定二极管阻抗随功率变化分析

简介&#xff1a;这套ADS仿真工程面向射频电路设计、射频匹配与二极管非线性特性研究人群&#xff0c;以HSMS2862肖特基二极管为对象&#xff0c;演示并解决了不同输入功率下二极管输入阻抗变化的测量与分析问题。压缩包共包含26个工程相关文件&#xff0c;涵盖cfg仿真配置、pr…

作者头像 李华
网站建设 2026/9/1 6:33:35

用物理光学法从零计算雷达散射截面:Python源码与工程实践

简介&#xff1a;POFACETS是一套基于物理光学近似预测雷达散射截面&#xff08;简称RCS&#xff09;的MATLAB项目源码&#xff0c;面向电磁散射计算、雷达隐身效果评估、目标特性分析等应用需求&#xff0c;也适合没有专门商业软件的研究者开展快速估算与算法验证。压缩包内共有…

作者头像 李华