各类排序算法可视化动作演示(冒泡,快排,选择,插入,归并,堆排序)
一篇可以让你体验数据结构排序的快乐。宝子们,可自行粘贴代码运行体验!
·
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>排序算法可视化</title>
<script src="https://cdn.tailwindcss.com/3.3.3"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
<style>
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
color: #2d3748;
}
.glassmorphism {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 12px 28px 0 rgba(31, 38, 135, 0.2);
}
.chart-container {
height: 400px;
width: 100%;
position: relative;
}
.bar {
transition: all 0.3s ease;
}
.highlight-bar {
background-color: #ef4444 !important;
}
.compare-bar {
background-color: #f59e0b !important;
}
.sorted-bar {
background-color: #10b981 !important;
}
.pivot-bar {
background-color: #8b5cf6 !important;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
.animate-pulse-slow {
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.mobile-menu {
position: absolute;
top: 100%;
left: 0;
right: 0;
padding: 1rem;
margin: 0.5rem;
border-radius: 0.75rem;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
transform-origin: top;
transform: scaleY(0);
opacity: 0;
transition: transform 0.3s ease, opacity 0.3s ease;
z-index: 100;
}
.mobile-menu.active {
transform: scaleY(1);
opacity: 1;
}
</style>
</head>
<body class="min-h-screen">
<!-- 导航条 -->
<nav class="glassmorphism sticky top-0 z-50 p-4 mb-8" id="mainNav">
<div class="container mx-auto flex items-center justify-between">
<div class="text-xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 text-transparent bg-clip-text">
<i class="fas fa-sort-amount-down mr-2"></i>排序算法可视化
</div>
<div class="hidden md:flex space-x-6">
<a href="#bubble-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">冒泡排序</a>
<a href="#selection-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">选择排序</a>
<a href="#insertion-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">插入排序</a>
<a href="#merge-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">归并排序</a>
<a href="#quick-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">快速排序</a>
<a href="#heap-sort" class="text-gray-600 hover:text-indigo-600 transition-colors">堆排序</a>
</div>
<button class="md:hidden text-gray-600 focus:outline-none" id="mobileMenuButton" aria-label="导航菜单">
<i class="fas fa-bars"></i>
</button>
<!-- 移动端导航菜单 -->
<div class="mobile-menu md:hidden" id="mobileMenu">
<a href="#bubble-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-bullseye mr-3 text-indigo-500"></i>冒泡排序
</a>
<a href="#selection-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-mouse-pointer mr-3 text-indigo-500"></i>选择排序
</a>
<a href="#insertion-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-keyboard mr-3 text-indigo-500"></i>插入排序
</a>
<a href="#merge-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-code-branch mr-3 text-indigo-500"></i>归并排序
</a>
<a href="#quick-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-bolt mr-3 text-indigo-500"></i>快速排序
</a>
<a href="#heap-sort" class="text-gray-600 hover:text-indigo-600 transition-colors flex items-center">
<i class="fas fa-tree mr-3 text-indigo-500"></i>堆排序
</a>
</div>
</div>
</nav>
<div class="container mx-auto px-4 py-8">
<!-- 冒泡排序页面 -->
<section id="bubble-sort" class="glassmorphism p-8 mb-8">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 mr-4">
<i class="fas fa-bullseye"></i>
</div>
<h2 class="text-2xl font-bold">冒泡排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。</p>
<div class="flex items-center space-x-4">
<button id="bubble-sort-btn" class="px-6 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="bubble-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="bubble-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
<!-- 选择排序页面 -->
<section id="selection-sort" class="glassmorphism p-8 mb-8" style="display: none;">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-4">
<i class="fas fa-mouse-pointer"></i>
</div>
<h2 class="text-2xl font-bold">选择排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">选择排序是一种简单直观的排序算法,它的工作原理是每次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置。</p>
<div class="flex items-center space-x-4">
<button id="selection-sort-btn" class="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="selection-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="selection-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
<!-- 插入排序页面 -->
<section id="insertion-sort" class="glassmorphism p-8 mb-8" style="display: none;">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-green-600 mr-4">
<i class="fas fa-keyboard"></i>
</div>
<h2 class="text-2xl font-bold">插入排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。</p>
<div class="flex items-center space-x-4">
<button id="insertion-sort-btn" class="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="insertion-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="insertion-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
<!-- 归并排序页面 -->
<section id="merge-sort" class="glassmorphism p-8 mb-8" style="display: none;">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600 mr-4">
<i class="fas fa-code-branch"></i>
</div>
<h2 class="text-2xl font-bold">归并排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列。</p>
<div class="flex items-center space-x-4">
<button id="merge-sort-btn" class="px-6 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="merge-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="merge-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
<!-- 快速排序页面 -->
<section id="quick-sort" class="glassmorphism p-8 mb-8" style="display: none;">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600 mr-4">
<i class="fas fa-bolt"></i>
</div>
<h2 class="text-2xl font-bold">快速排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">快速排序使用分治法策略来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。</p>
<div class="flex items-center space-x-4">
<button id="quick-sort-btn" class="px-6 py-2 bg-yellow-600 text-white rounded-lg hover:bg-yellow-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="quick-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="quick-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
<!-- 堆排序页面 -->
<section id="heap-sort" class="glassmorphism p-8 mb-8" style="display: none;">
<div class="flex items-center mb-6">
<div class="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center text-red-600 mr-4">
<i class="fas fa-tree"></i>
</div>
<h2 class="text-2xl font-bold">堆排序</h2>
</div>
<div class="mb-6">
<p class="text-gray-600 mb-4">堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质。</p>
<div class="flex items-center space-x-4">
<button id="heap-sort-btn" class="px-6 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors">
<i class="fas fa-play mr-2"></i>开始排序
</button>
<button id="heap-reset-btn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors">
<i class="fas fa-redo mr-2"></i>重置数据
</button>
</div>
</div>
<div class="chart-container">
<div id="heap-chart" class="flex items-end h-full w-full space-x-1"></div>
</div>
</section>
</div>
<footer class="bg-gray-100 py-6 mt-12">
<div class="container mx-auto px-4 text-center text-gray-500">
<p>created by <a class="text-indigo-600 hover:text-indigo-800">CSDN:子丫鱼</a></p>
<p class="mt-2">页面内容仅供学习</p>
</div>
</footer>
<script>
// 常量定义
const NUM_BARS = 20;
const MAX_HEIGHT = 350;
const SPEED = 100; // 排序动画速度(毫秒)
// 数据数组
let bubbleData = [];
let selectionData = [];
let insertionData = [];
let mergeData = [];
let quickData = [];
let heapData = [];
// 初始化函数
function init() {
generateData();
setupEventListeners();
showPage('bubble-sort');
}
// 生成随机数据
function generateData() {
bubbleData = [];
selectionData = [];
insertionData = [];
mergeData = [];
quickData = [];
heapData = [];
for (let i = 0; i < NUM_BARS; i++) {
const height = Math.floor(Math.random() * MAX_HEIGHT) + 10;
bubbleData.push(height);
selectionData.push(height);
insertionData.push(height);
mergeData.push(height);
quickData.push(height);
heapData.push(height);
}
renderChart('bubble-chart', bubbleData);
renderChart('selection-chart', selectionData);
renderChart('insertion-chart', insertionData);
renderChart('merge-chart', mergeData);
renderChart('quick-chart', quickData);
renderChart('heap-chart', heapData);
}
// 渲染图表
function renderChart(chartId, data) {
const chart = document.getElementById(chartId);
chart.innerHTML = '';
const maxValue = Math.max(...data);
const minWidth = 20;
const maxWidth = 40;
const widthStep = (maxWidth - minWidth) / NUM_BARS;
data.forEach((height, index) => {
const bar = document.createElement('div');
bar.className = 'bar bg-indigo-500 rounded-t-md';
bar.style.height = `${height}px`;
bar.style.width = `${maxWidth - (index * widthStep)}px`;
bar.dataset.value = height;
chart.appendChild(bar);
});
}
// 设置事件监听器
function setupEventListeners() {
// 导航菜单
document.getElementById('mobileMenuButton').addEventListener('click', toggleMobileMenu);
// 排序按钮
document.getElementById('bubble-sort-btn').addEventListener('click', () => bubbleSort());
document.getElementById('selection-sort-btn').addEventListener('click', () => selectionSort());
document.getElementById('insertion-sort-btn').addEventListener('click', () => insertionSort());
document.getElementById('merge-sort-btn').addEventListener('click', () => mergeSort());
document.getElementById('quick-sort-btn').addEventListener('click', () => quickSort());
document.getElementById('heap-sort-btn').addEventListener('click', () => heapSort());
// 重置按钮
document.getElementById('bubble-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('bubble-sort-btn').disabled = false;
});
document.getElementById('selection-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('selection-sort-btn').disabled = false;
});
document.getElementById('insertion-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('insertion-sort-btn').disabled = false;
});
document.getElementById('merge-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('merge-sort-btn').disabled = false;
});
document.getElementById('quick-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('quick-sort-btn').disabled = false;
});
document.getElementById('heap-reset-btn').addEventListener('click', () => {
generateData();
document.getElementById('heap-sort-btn').disabled = false;
});
// 导航链接
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
showPage(this.getAttribute('href').substring(1));
// 如果是移动端菜单,点击后关闭菜单
if (window.innerWidth < 768) {
toggleMobileMenu();
}
// 平滑滚动到对应部分
document.getElementById(this.getAttribute('href').substring(1)).scrollIntoView({
behavior: 'smooth'
});
});
});
}
// 显示页面
function showPage(pageId) {
const sections = document.querySelectorAll('section');
sections.forEach(section => {
section.style.display = 'none';
});
document.getElementById(pageId).style.display = 'block';
}
// 切换移动端菜单
function toggleMobileMenu() {
const mobileMenu = document.getElementById('mobileMenu');
const menuIcon = document.querySelector('#mobileMenuButton i');
mobileMenu.classList.toggle('active');
if (mobileMenu.classList.contains('active')) {
menuIcon.classList.remove('fa-bars');
menuIcon.classList.add('fa-times');
} else {
menuIcon.classList.remove('fa-times');
menuIcon.classList.add('fa-bars');
}
}
// 交换两个元素的高度
async function swapBars(chartId, index1, index2, dataArray) {
const chart = document.getElementById(chartId);
const bars = chart.children;
// 高亮要交换的两个柱子
bars[index1].classList.add('highlight-bar');
bars[index2].classList.add('highlight-bar');
// 等待动画
await new Promise(resolve => setTimeout(resolve, SPEED));
// 交换数据
[dataArray[index1], dataArray[index2]] = [dataArray[index2], dataArray[index1]];
// 更新DOM
bars[index1].style.height = `${dataArray[index1]}px`;
bars[index2].style.height = `${dataArray[index2]}px`;
// 移除高亮
bars[index1].classList.remove('highlight-bar');
bars[index2].classList.remove('highlight-bar');
}
// 冒泡排序
async function bubbleSort() {
document.getElementById('bubble-sort-btn').disabled = true;
const chartId = 'bubble-chart';
const chart = document.getElementById(chartId);
const bars = chart.children;
for (let i = 0; i < bubbleData.length - 1; i++) {
for (let j = 0; j < bubbleData.length - i - 1; j++) {
// 高亮比较的两个柱子
bars[j].classList.add('compare-bar');
bars[j + 1].classList.add('compare-bar');
await new Promise(resolve => setTimeout(resolve, SPEED));
if (bubbleData[j] > bubbleData[j + 1]) {
await swapBars(chartId, j, j + 1, bubbleData);
}
// 移除高亮
bars[j].classList.remove('compare-bar');
bars[j + 1].classList.remove('compare-bar');
}
// 标记已排序的元素
bars[bubbleData.length - i - 1].classList.add('sorted-bar');
}
// 标记第一个元素为已排序
bars[0].classList.add('sorted-bar');
}
// 选择排序
async function selectionSort() {
document.getElementById('selection-sort-btn').disabled = true;
const chartId = 'selection-chart';
const chart = document.getElementById(chartId);
const bars = chart.children;
for (let i = 0; i < selectionData.length - 1; i++) {
let minIndex = i;
// 高亮当前最小值
bars[minIndex].classList.add('highlight-bar');
for (let j = i + 1; j < selectionData.length; j++) {
// 高亮当前比较的元素
bars[j].classList.add('compare-bar');
await new Promise(resolve => setTimeout(resolve, SPEED));
if (selectionData[j] < selectionData[minIndex]) {
// 移除之前最小值的高亮
bars[minIndex].classList.remove('highlight-bar');
minIndex = j;
// 高亮新的最小值
bars[minIndex].classList.add('highlight-bar');
}
// 移除比较的高亮
bars[j].classList.remove('compare-bar');
}
if (minIndex !== i) {
await swapBars(chartId, i, minIndex, selectionData);
}
// 标记已排序的元素
bars[i].classList.add('sorted-bar');
}
// 标记最后一个元素为已排序
bars[selectionData.length - 1].classList.add('sorted-bar');
}
// 插入排序
async function insertionSort() {
document.getElementById('insertion-sort-btn').disabled = true;
const chartId = 'insertion-chart';
const chart = document.getElementById(chartId);
const bars = chart.children;
for (let i = 1; i < insertionData.length; i++) {
let j = i;
// 高亮当前处理的元素
bars[j].classList.add('highlight-bar');
while (j > 0 && insertionData[j] < insertionData[j - 1]) {
// 高亮比较的元素
bars[j - 1].classList.add('compare-bar');
await new Promise(resolve => setTimeout(resolve, SPEED));
await swapBars(chartId, j, j - 1, insertionData);
// 移除比较的高亮
bars[j].classList.remove('compare-bar');
j--;
}
// 移除高亮
bars[j].classList.remove('highlight-bar');
// 标记已排序的部分
for (let k = 0; k <= i; k++) {
bars[k].classList.add('sorted-bar');
}
}
}
// 归并排序
async function mergeSort() {
document.getElementById('merge-sort-btn').disabled = true;
await mergeSortHelper('merge-chart', mergeData, 0, mergeData.length - 1);
// 标记所有元素为已排序
const chart = document.getElementById('merge-chart');
const bars = chart.children;
for (let i = 0; i < bars.length; i++) {
bars[i].classList.add('sorted-bar');
}
}
async function mergeSortHelper(chartId, arr, left, right) {
if (left < right) {
const mid = Math.floor((left + right) / 2);
await mergeSortHelper(chartId, arr, left, mid);
await mergeSortHelper(chartId, arr, mid + 1, right);
await merge(chartId, arr, left, mid, right);
}
}
async function merge(chartId, arr, left, mid, right) {
const chart = document.getElementById(chartId);
const bars = chart.children;
const n1 = mid - left + 1;
const n2 = right - mid;
const L = new Array(n1);
const R = new Array(n2);
for (let i = 0; i < n1; i++) {
L[i] = arr[left + i];
bars[left + i].classList.add('highlight-bar');
}
for (let j = 0; j < n2; j++) {
R[j] = arr[mid + 1 + j];
bars[mid + 1 + j].classList.add('compare-bar');
}
await new Promise(resolve => setTimeout(resolve, SPEED));
let i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
bars[k].style.height = `${arr[k]}px`;
i++;
} else {
arr[k] = R[j];
bars[k].style.height = `${arr[k]}px`;
j++;
}
await new Promise(resolve => setTimeout(resolve, SPEED));
k++;
}
while (i < n1) {
arr[k] = L[i];
bars[k].style.height = `${arr[k]}px`;
i++;
k++;
await new Promise(resolve => setTimeout(resolve, SPEED));
}
while (j < n2) {
arr[k] = R[j];
bars[k].style.height = `${arr[k]}px`;
j++;
k++;
await new Promise(resolve => setTimeout(resolve, SPEED));
}
// 移除高亮
for (let i = left; i <= right; i++) {
bars[i].classList.remove('highlight-bar');
bars[i].classList.remove('compare-bar');
}
}
// 快速排序
async function quickSort() {
document.getElementById('quick-sort-btn').disabled = true;
await quickSortHelper('quick-chart', quickData, 0, quickData.length - 1);
// 标记所有元素为已排序
const chart = document.getElementById('quick-chart');
const bars = chart.children;
for (let i = 0; i < bars.length; i++) {
bars[i].classList.add('sorted-bar');
}
}
async function quickSortHelper(chartId, arr, low, high) {
if (low < high) {
const pi = await partition(chartId, arr, low, high);
await quickSortHelper(chartId, arr, low, pi - 1);
await quickSortHelper(chartId, arr, pi + 1, high);
}
}
async function partition(chartId, arr, low, high) {
const chart = document.getElementById(chartId);
const bars = chart.children;
const pivot = arr[high];
bars[high].classList.add('pivot-bar');
let i = low - 1;
for (let j = low; j < high; j++) {
bars[j].classList.add('compare-bar');
await new Promise(resolve => setTimeout(resolve, SPEED));
if (arr[j] < pivot) {
i++;
await swapBars(chartId, i, j, arr);
}
bars[j].classList.remove('compare-bar');
}
await swapBars(chartId, i + 1, high, arr);
bars[high].classList.remove('pivot-bar');
return i + 1;
}
// 堆排序
async function heapSort() {
document.getElementById('heap-sort-btn').disabled = true;
const chartId = 'heap-chart';
const chart = document.getElementById(chartId);
const bars = chart.children;
const n = heapData.length;
// 构建最大堆
for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
await heapify(chartId, heapData, n, i);
}
// 一个个从堆顶取出元素
for (let i = n - 1; i > 0; i--) {
// 移动当前根到末尾
await swapBars(chartId, 0, i, heapData);
// 标记已排序的元素
bars[i].classList.add('sorted-bar');
// 对剩下的元素重新构建堆
await heapify(chartId, heapData, i, 0);
}
// 标记第一个元素为已排序
bars[0].classList.add('sorted-bar');
}
async function heapify(chartId, arr, n, i) {
const chart = document.getElementById(chartId);
const bars = chart.children;
let largest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
// 高亮当前节点和子节点
bars[i].classList.add('highlight-bar');
if (left < n) bars[left].classList.add('compare-bar');
if (right < n) bars[right].classList.add('compare-bar');
await new Promise(resolve => setTimeout(resolve, SPEED));
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
await swapBars(chartId, i, largest, arr);
await heapify(chartId, arr, n, largest);
}
// 移除高亮
bars[i].classList.remove('highlight-bar');
if (left < n) bars[left].classList.remove('compare-bar');
if (right < n) bars[right].classList.remove('compare-bar');
}
// 初始化应用
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)