diff --git a/src/algorithms/sorting/bubbleSort.js b/src/algorithms/sorting/bubbleSort.js
new file mode 100644
index 0000000..71fe43d
--- /dev/null
+++ b/src/algorithms/sorting/bubbleSort.js
@@ -0,0 +1,24 @@
+// src/algorithms/sorting/bubbleSort.js
+export function* bubbleSort(array) {
+ const arr = [...array];
+ const n = arr.length;
+
+ // Standard bubble sort with generator events
+ for (let i = 0; i < n - 1; i++) {
+ // After each pass, the largest element of the unsorted portion bubbles to position n-1-i
+ for (let j = 0; j < n - 1 - i; j++) {
+ // compare pair (j, j+1)
+ yield { type: "compare", indices: [j, j + 1] };
+
+ if (arr[j] > arr[j + 1]) {
+ [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
+ yield { type: "swap", indices: [j, j + 1], array: [...arr] };
+ }
+ }
+
+ // mark the settled position at the end of this pass
+ yield { type: "min", index: n - 1 - i };
+ }
+
+ yield { type: "done", array: arr };
+}
\ No newline at end of file
diff --git a/src/components/sorting/BubbleSortVisualizer.jsx b/src/components/sorting/BubbleSortVisualizer.jsx
new file mode 100644
index 0000000..3b7c24f
--- /dev/null
+++ b/src/components/sorting/BubbleSortVisualizer.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 BubbleSortVisualizer({ 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 (
+
+ );
+ })}
+
+ );
+}
\ No newline at end of file
diff --git a/src/pages/sorting/BubbleSort.jsx b/src/pages/sorting/BubbleSort.jsx
new file mode 100644
index 0000000..261bba0
--- /dev/null
+++ b/src/pages/sorting/BubbleSort.jsx
@@ -0,0 +1,83 @@
+import React, { useState } from "react";
+import { Toaster } from "react-hot-toast";
+import BubbleSortVisualizer from "../../components/sorting/BubbleSortVisualizer";
+import { bubbleSort } from "../../algorithms/sorting/bubbleSort";
+
+export default function BubbleSort() {
+ 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 = bubbleSort(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 (
+
+
+
+ Bubble Sort Visualizer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/pages/sorting/SortingPage.jsx b/src/pages/sorting/SortingPage.jsx
index 8d8ab88..6422058 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 BubbleSort from "./BubbleSort";
import InsertionSort from "./InsertionSort";
export default function SortingPage() {
@@ -13,7 +14,8 @@ export default function SortingPage() {
case "insertion":
return ;
// You can add more later like:
- // case "bubble": return ;
+ case "bubble":
+ return ;
// case "merge": return ;
default:
return (
@@ -40,6 +42,7 @@ export default function SortingPage() {
>
+