updating the animation

This commit is contained in:
Jidong Xiao
2025-04-21 17:10:37 -04:00
committed by JamesFlare1212
parent c24a7592ab
commit 7b9d3983ed

View File

@@ -1,5 +1,3 @@
//AUTHOR: Chloe Lee
// initial array to be sorted
let array = [5, 3, 8, 1, 9, 4];
let currentStep = 0;
@@ -32,7 +30,6 @@ const codeLines = [
];
function initialize() {
// Display code with line numbers
const codeElement = document.getElementById('code');
let codeHTML = '';
@@ -106,6 +103,8 @@ function updateArrayDisplay() {
element.classList.add('swap');
} else if (animationSteps[currentStep] && animationSteps[currentStep].sorted && animationSteps[currentStep].sorted.includes(index)) {
element.classList.add('done');
} else if (animationSteps[currentStep] && animationSteps[currentStep].activeHeap && index < animationSteps[currentStep].heapSize) {
element.classList.add('active-heap');
}
element.textContent = value;
@@ -185,7 +184,6 @@ function drawHeapTree() {
}
}
// !! subject to change !!
for (let i = 0; i < Math.min(array.length, positions.length); i++) {
if (i < heapSize) {
// determine node color based on current operation
@@ -204,6 +202,10 @@ function drawHeapTree() {
animationSteps[currentStep].sorted.includes(i)) {
nodeColor = '#81ecec';
borderColor = '#00cec9';
} else if (animationSteps[currentStep] && animationSteps[currentStep].activeHeap && i < animationSteps[currentStep].heapSize) {
// highlight active heap nodes
nodeColor = '#a3d8f4';
borderColor = '#0984e3';
}
// draw rectangle with round corners
@@ -244,18 +246,21 @@ function drawHeapTree() {
function generateAnimationSteps() {
animationSteps = [];
let tempArray = [...array];
const originalArray = [5, 3, 8, 1, 9, 4];
let tempArray = [...originalArray];
const n = tempArray.length;
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 0,
description: 'Starting heap sort with array [' + tempArray.join(', ') + ']',
description: 'Starting heap sort with array [' + originalArray.join(', ') + ']',
heapSize: n
});
// build max-heap
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 2,
description: 'Building max heap',
heapSize: n
@@ -265,26 +270,36 @@ function generateAnimationSteps() {
for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 3,
description: `Heapifying subtree rooted at index ${i}`,
heapSize: n,
comparing: [i]
});
heapifyWithAnimation(tempArray, n, i, sortedIndices);
heapifyWithAnimation(tempArray, n, i, sortedIndices, originalArray);
}
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 6,
description: 'Max heap built. Extracting elements one by one',
heapSize: n
});
for (let i = n - 1; i > 0; i--) {
// highlight the active heap portion before swap
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 7,
description: `Current active heap size: ${i+1}. Elements from index 0 to ${i} need to be processed.`,
heapSize: i + 1,
activeHeap: true,
sorted: [...sortedIndices]
});
animationSteps.push({
array: [...originalArray],
line: 8,
description: `Swapping root (${tempArray[0]}) with element at index ${i} (${tempArray[i]})`,
heapSize: i + 1,
@@ -297,7 +312,7 @@ function generateAnimationSteps() {
sortedIndices.push(i);
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 8,
description: `Element ${tempArray[i]} is now in its correct position`,
heapSize: i,
@@ -305,18 +320,20 @@ function generateAnimationSteps() {
});
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 11,
description: `Heapifying reduced heap (size ${i})`,
heapSize: i
heapSize: i,
activeHeap: true,
sorted: [...sortedIndices]
});
heapifyWithAnimation(tempArray, i, 0, sortedIndices);
heapifyWithAnimation(tempArray, i, 0, sortedIndices, originalArray);
}
sortedIndices.push(0);
animationSteps.push({
array: [...tempArray],
array: [...originalArray],
line: 13,
description: 'Heap sort complete! Array is now sorted: [' + tempArray.join(', ') + ']',
heapSize: n,
@@ -325,13 +342,13 @@ function generateAnimationSteps() {
}
// heapify function that records animation steps
function heapifyWithAnimation(arr, n, i, sortedIndices) {
function heapifyWithAnimation(arr, n, i, sortedIndices, originalArray) {
let largest = i;
const left = 2 * i + 1;
const right = 2 * i + 2;
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 16,
description: `Heapifying at index ${i}`,
heapSize: n,
@@ -342,7 +359,7 @@ function heapifyWithAnimation(arr, n, i, sortedIndices) {
// compare with left child
if (left < n) {
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 21,
description: `Comparing ${arr[i]} (index ${i}) with left child ${arr[left]} (index ${left})`,
heapSize: n,
@@ -354,20 +371,39 @@ function heapifyWithAnimation(arr, n, i, sortedIndices) {
largest = left;
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 22,
description: `Left child ${arr[left]} is larger than current largest ${arr[i]}`,
heapSize: n,
comparing: [largest],
sorted: sortedIndices ? [...sortedIndices] : []
});
} else {
animationSteps.push({
array: [...originalArray],
line: 21,
description: `No action needed: ${arr[i]} (index ${i}) is already larger than or equal to its left child ${arr[left]} (index ${left})`,
heapSize: n,
comparing: [i],
sorted: sortedIndices ? [...sortedIndices] : []
});
}
} else {
// no left child
animationSteps.push({
array: [...originalArray],
line: 21,
description: `No left child exists for node at index ${i}`,
heapSize: n,
comparing: [i],
sorted: sortedIndices ? [...sortedIndices] : []
});
}
// compare with right child
if (right < n) {
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 25,
description: `Comparing ${arr[largest]} (index ${largest}) with right child ${arr[right]} (index ${right})`,
heapSize: n,
@@ -379,20 +415,39 @@ function heapifyWithAnimation(arr, n, i, sortedIndices) {
largest = right;
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 26,
description: `Right child ${arr[right]} is larger than current largest ${arr[largest === i ? arr[i] : arr[left]]}`,
heapSize: n,
comparing: [largest],
sorted: sortedIndices ? [...sortedIndices] : []
});
} else {
animationSteps.push({
array: [...originalArray],
line: 25,
description: `No action needed: ${arr[largest]} (index ${largest}) is already larger than or equal to its right child ${arr[right]} (index ${right})`,
heapSize: n,
comparing: [largest],
sorted: sortedIndices ? [...sortedIndices] : []
});
}
} else {
// there is no right child
animationSteps.push({
array: [...originalArray],
line: 25,
description: `No right child exists for node at index ${i}`,
heapSize: n,
comparing: [i],
sorted: sortedIndices ? [...sortedIndices] : []
});
}
// if largest is not root, swap and heapify
if (largest !== i) {
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 30,
description: `Swapping ${arr[i]} (index ${i}) with ${arr[largest]} (index ${largest})`,
heapSize: n,
@@ -403,7 +458,7 @@ function heapifyWithAnimation(arr, n, i, sortedIndices) {
[arr[i], arr[largest]] = [arr[largest], arr[i]];
animationSteps.push({
array: [...arr],
array: [...originalArray],
line: 33,
description: `Recursively heapifying the affected subtree rooted at index ${largest}`,
heapSize: n,
@@ -411,7 +466,17 @@ function heapifyWithAnimation(arr, n, i, sortedIndices) {
sorted: sortedIndices ? [...sortedIndices] : []
});
heapifyWithAnimation(arr, n, largest, sortedIndices);
heapifyWithAnimation(arr, n, largest, sortedIndices, originalArray);
} else {
// add explanation when no swap is needed
animationSteps.push({
array: [...originalArray],
line: 30,
description: `No swap needed: Element at index ${i} (${arr[i]}) is already in correct position for max heap`,
heapSize: n,
comparing: [i],
sorted: sortedIndices ? [...sortedIndices] : []
});
}
}
@@ -419,7 +484,7 @@ function nextStep() {
if (currentStep < animationSteps.length - 1) {
currentStep++;
// update the array to current state
// always use the original array for display
if (animationSteps[currentStep] && animationSteps[currentStep].array) {
array = [...animationSteps[currentStep].array];
}