You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

冒泡排序可视化工具:点击Next按钮实现元素交换功能问题排查

冒泡排序可视化工具问题修复方案

原代码核心问题

  1. 重复绑定点击事件:页面加载时就执行双重循环绑定点击事件,但此时newArray是空数组,循环不会执行;就算数组有值,也会给按钮绑定几十次点击事件,点击一次触发所有逻辑,完全混乱。
  2. 交换逻辑错误:使用order属性交换时,赋值的是原数组的旧值,且DOM元素的类名未同步更新,后续对比会找错元素。
  3. 无步骤跟踪:没有记录当前执行到冒泡排序的哪一步,无法实现点击Next逐步执行的效果。
  4. 缺少高亮反馈:没有实现对比元素的高亮,用户无法直观看到当前操作的元素。

修正后的完整代码

HTML

<label>Enter numbers seperated by comma here</label>
<input type="text" id="numbers_input">
<button type="button" id="create-btn">Create Array</button>
<div class="num-holder"></div>
<button id="sort-btn" class="sort-btn" type="button">Next</button>

<script src="index.js"></script>

CSS

.num-holder {
  display: flex;
  justify-content: space-between;
  margin-top: 50px;
  margin-bottom: 10px;
  gap: 10px;
}

.num {
  background-color: rgba(227, 130, 130, 0.53);
  font-size: 30px;
  padding: 10px 20px;
  transition: background-color 0.3s;
}

/* 高亮当前对比的元素 */
.num.highlight {
  background-color: #ffd966;
}

/* 标记已排序完成的元素(可选) */
.num.sorted {
  background-color: #93c47d;
}

.as-console-wrapper { height: 40px }

JavaScript

let createBtn = document.getElementById('create-btn');
let sortBtn = document.getElementById('sort-btn');
let numHolder = document.querySelector('.num-holder');
let newArray = [];
// 跟踪冒泡排序的当前步骤
let currentI = 0;
let currentJ = 0;

createBtn.addEventListener('click', () => {
  // 清空之前的数组和DOM元素
  newArray = [];
  numHolder.innerHTML = '';
  currentI = 0;
  currentJ = 0;

  // 解析输入为数字数组,过滤无效值
  let data = document.getElementById('numbers_input').value;
  let newData = data.split(',').map(num => Number(num)).filter(num => !isNaN(num));
  if (newData.length < 2) {
    alert('请输入至少两个有效数字');
    return;
  }
  newArray = [...newData];

  // 创建DOM元素
  newArray.forEach((num, index) => {
    const div = document.createElement('div');
    div.innerHTML = num;
    div.className = `num num-${index}`;
    div.setAttribute('data-val', num);
    numHolder.appendChild(div);
  });
});

sortBtn.addEventListener('click', () => {
  if (newArray.length === 0) {
    alert('请先创建数组');
    return;
  }

  // 移除之前的高亮标记
  document.querySelectorAll('.num.highlight').forEach(el => el.classList.remove('highlight'));

  // 冒泡排序终止条件:所有外层循环完成
  if (currentI >= newArray.length - 1) {
    alert('排序完成');
    return;
  }

  // 获取当前要对比的两个元素
  let num1El = document.querySelector(`.num-${currentJ}`);
  let num2El = document.querySelector(`.num-${currentJ + 1}`);
  if (!num1El || !num2El) return;

  // 高亮当前对比元素
  num1El.classList.add('highlight');
  num2El.classList.add('highlight');

  // 对比并交换
  let num1 = parseInt(num1El.getAttribute('data-val'));
  let num2 = parseInt(num2El.getAttribute('data-val'));
  if (num1 > num2) {
    // 交换数组中的值
    [newArray[currentJ], newArray[currentJ + 1]] = [newArray[currentJ + 1], newArray[currentJ]];
    // 交换DOM元素的内容和data-val属性
    [num1El.innerHTML, num2El.innerHTML] = [num2El.innerHTML, num1El.innerHTML];
    [num1El.dataset.val, num2El.dataset.val] = [num2El.dataset.val, num1El.dataset.val];
  }

  // 推进到下一个步骤
  currentJ++;
  // 内层循环完成,推进外层循环,重置内层循环索引
  if (currentJ >= newArray.length - currentI - 1) {
    currentI++;
    currentJ = 0;
    // 标记已排序完成的元素
    document.querySelector(`.num-${newArray.length - currentI}`)?.classList.add('sorted');
  }
});

关键改动说明

  1. 步骤跟踪:用currentI和currentJ两个变量记录当前冒泡排序执行到外层和内层循环的哪一步,每次点击Next只执行当前步骤的逻辑。
  2. 单次点击事件绑定:只给Sort按钮绑定一次点击事件,避免重复绑定导致的逻辑混乱。
  3. 正确的交换逻辑:同时交换数组中的值和DOM元素的内容、data-val属性,确保数据和视图同步,不需要依赖order属性(直接交换内容更直观)。
  4. 高亮效果:添加highlight类标记当前对比的元素,额外添加sorted类标记已完成排序的元素,提升可视化体验。
  5. 边界处理:添加数组为空、输入无效、排序完成的提示,避免报错。

内容的提问来源于stack exchange,提问作者Md Amir Sohail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:54:28