diff --git a/src/algorithms/sorting/InsertionSort.js b/src/algorithms/sorting/InsertionSort.js new file mode 100644 index 0000000..71faff6 --- /dev/null +++ b/src/algorithms/sorting/InsertionSort.js @@ -0,0 +1,34 @@ +// src/algorithms/sorting/InsertionSort.js +export function* insertionSort(array) { + const arr = [...array]; + const n = arr.length; + + for (let i = 1; i < n; i++) { + // mark the current index being considered (matches selectionSort behavior) + yield { type: "compare", indices: [i] }; + + // perform insertion by swapping adjacent elements until correct position + let j = i; + while (j > 0) { + // compare the pair we're about to potentially swap + yield { type: "compare", indices: [j - 1, j] }; + + if (arr[j - 1] > arr[j]) { + // swap adjacent + [arr[j - 1], arr[j]] = [arr[j], arr[j - 1]]; + yield { type: "swap", indices: [j - 1, j], array: [...arr] }; + j--; + } else { + break; + } + } + + // if element moved, indicate insertion position (use "min" to match visual cue) + if (j !== i) { + yield { type: "min", index: j }; + } + } + + yield { type: "done", array: arr }; +} + diff --git a/src/components/sorting/InsertionSortVisualizer.jsx b/src/components/sorting/InsertionSortVisualizer.jsx new file mode 100644 index 0000000..cf4e687 --- /dev/null +++ b/src/components/sorting/InsertionSortVisualizer.jsx @@ -0,0 +1,38 @@ +import React from "react"; + +const COLORS = { + default: "bg-blue-500 shadow-[0_0_10px_#3b82f6]", + comparing: "bg-yellow-400 shadow-[0_0_12px_#facc15]", + min: "bg-green-500 shadow-[0_0_12px_#22c55e]", + swap: "bg-red-500 shadow-[0_0_12px_#ef4444]", +}; + +export default function InsertionSortVisualizer({ array, highlight }) { + const maxValue = Math.max(...array, 1); // Avoid division by zero + const containerHeight = 288; // px (matches h-72) + + return ( +
+ {array.map((value, idx) => { + let color = COLORS.default; + if (highlight?.type === "compare" && highlight.indices?.includes(idx)) + color = COLORS.comparing; + if (highlight?.type === "min" && highlight.index === idx) + color = COLORS.min; + if (highlight?.type === "swap" && highlight.indices?.includes(idx)) + color = COLORS.swap; + + // Normalize height relative to the maximum value + const height = Math.max((value / maxValue) * containerHeight, 15); // minimum 15px for visibility + + return ( +
+ ); + })} +
+ ); +} diff --git a/src/pages/sorting/InsertionSort.jsx b/src/pages/sorting/InsertionSort.jsx new file mode 100644 index 0000000..3018c2b --- /dev/null +++ b/src/pages/sorting/InsertionSort.jsx @@ -0,0 +1,84 @@ +import React, { useState } from "react"; +import { Toaster } from "react-hot-toast"; +import InsertionSortVisualizer from "../../components/sorting/InsertionSortVisualizer"; +import { insertionSort } from "../../algorithms/sorting/InsertionSort"; + +export default function InsertionSort() { + const [array, setArray] = useState([]); + const [input, setInput] = useState(""); + const [highlight, setHighlight] = useState(null); + const [isRunning, setIsRunning] = useState(false); + + const handleStart = async () => { + if (isRunning || array.length === 0) return; + setIsRunning(true); + + const gen = insertionSort(array); + for (let step of gen) { + setHighlight(step); + if (step.array) setArray([...step.array]); + await new Promise((r) => setTimeout(r, 500)); + } + + setHighlight({ type: "done" }); + setIsRunning(false); + }; + + const handleReset = () => { + setArray([]); + setInput(""); + setHighlight(null); + }; + + const handleInput = (e) => { + setInput(e.target.value); + const numbers = e.target.value + .split(",") + .map((n) => parseInt(n.trim())) + .filter((n) => !isNaN(n)); + setArray(numbers); + }; + + return ( +
+ +

+ Insertion Sort Visualizer +

+ + + +
+ + +
+ +
+ +
+ +
+ ); +} + diff --git a/src/pages/sorting/SortingPage.jsx b/src/pages/sorting/SortingPage.jsx index e91d8c4..8d8ab88 100644 --- a/src/pages/sorting/SortingPage.jsx +++ b/src/pages/sorting/SortingPage.jsx @@ -1,6 +1,7 @@ // src/pages/SortingPage.jsx import React, { useState } from "react"; import SelectionSort from "./SelectionSort"; +import InsertionSort from "./InsertionSort"; export default function SortingPage() { const [selectedAlgo, setSelectedAlgo] = useState(""); @@ -9,6 +10,8 @@ export default function SortingPage() { switch (selectedAlgo) { case "selection": return ; + case "insertion": + return ; // You can add more later like: // case "bubble": return ; // case "merge": return ; @@ -37,6 +40,7 @@ export default function SortingPage() { > +