From 766246c108e7997a805338c07afb1e95ca47f457 Mon Sep 17 00:00:00 2001 From: Suraj Kumar Date: Tue, 14 Oct 2025 20:23:28 +0530 Subject: [PATCH] feat: Implement linear search Binary search will be implemented in further commits --- src/App.jsx | 2 + src/algorithms/searching/LinearSearch.js | 38 +++++ .../searching/LinearSearchVisualizer.jsx | 46 ++++++ src/pages/searching/linearSearch.jsx | 132 ++++++++++++++++++ src/pages/searching/searchingPage.jsx | 61 ++++++++ 5 files changed, 279 insertions(+) create mode 100644 src/algorithms/searching/LinearSearch.js create mode 100644 src/components/searching/LinearSearchVisualizer.jsx create mode 100644 src/pages/searching/linearSearch.jsx create mode 100644 src/pages/searching/searchingPage.jsx diff --git a/src/App.jsx b/src/App.jsx index f4a6d32..fa31c01 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -3,6 +3,7 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; // import UnionFindPage from "../src/pages/graph/UnionFind.jsx"; // ✅ Import Union-Find Page import SortingPage from "./pages/sorting/SortingPage"; import GraphPage from "./pages/graph/GraphPage"; +import Searchingpage from "./pages/searching/searchingPage"; import Homepage from "./pages/Homepage.jsx"; function App() { @@ -12,6 +13,7 @@ function App() { } /> {/* } /> */} } /> + } /> } /> diff --git a/src/algorithms/searching/LinearSearch.js b/src/algorithms/searching/LinearSearch.js new file mode 100644 index 0000000..7af3328 --- /dev/null +++ b/src/algorithms/searching/LinearSearch.js @@ -0,0 +1,38 @@ +/** + * A generator function that performs Linear Search and yields visualization steps. + * @param {number[]} array - The array to search through. + * @param {number} target - The value to find. + * @yields {{highlightIndex: number | null, foundIndex: number | null, message?: string}} + */ +export function* linearSearch(array, target) { + const targetNumber = parseInt(target); // Ensure target is a number + let foundIndex = null; + + // Iterate through the array + for (let i = 0; i < array.length; i++) { + // 1. Yield the current index being compared (yellow highlight) + yield { + highlightIndex: i, + foundIndex: foundIndex + }; + + // 2. Check for the target + if (array[i] === targetNumber) { + foundIndex = i; + // Target found, yield the final state (green) and return + yield { + highlightIndex: i, + foundIndex: foundIndex, + message: `Success! Found target ${targetNumber} at index ${i}` + }; + return; // Stop the generator + } + } + + // If the loop finishes without finding the target + yield { + highlightIndex: null, // Clear highlight + foundIndex: null, // Not found + message: `Target ${targetNumber} was not found in the array.` + }; +} \ No newline at end of file diff --git a/src/components/searching/LinearSearchVisualizer.jsx b/src/components/searching/LinearSearchVisualizer.jsx new file mode 100644 index 0000000..612c873 --- /dev/null +++ b/src/components/searching/LinearSearchVisualizer.jsx @@ -0,0 +1,46 @@ +import React from "react"; + +// Updated colors for searching visualization +const COLORS = { + default: "bg-blue-500 shadow-[0_0_10px_#3b82f6]", // Default bar color + comparing: "bg-yellow-400 shadow-[0_0_12px_#facc15]", // Element currently being checked + found: "bg-green-500 shadow-[0_0_12px_#22c55e]", // Target element found + miss: "bg-red-500 shadow-[0_0_12px_#ef4444]", // Optional: To highlight elements that were skipped (e.g., in Binary Search) +}; + +export default function LinearSearchVisualizer({ + array, + highlightIndex, + foundIndex +}) { + const maxValue = Math.max(...array, 1); + const containerHeight = 288; // px (matches h-72) + + return ( +
+ {array.map((value, idx) => { + let color = COLORS.default; + + // 1. Check if the element has been found (Highest priority for the final result) + if (foundIndex === idx) { + color = COLORS.found; + } + // 2. Check if the element is currently being compared + else if (highlightIndex === idx) { + color = COLORS.comparing; + } + + // Normalize height relative to the maximum value + const height = Math.max((value / maxValue) * containerHeight, 15); + + return ( +
+ ); + })} +
+ ); +} \ No newline at end of file diff --git a/src/pages/searching/linearSearch.jsx b/src/pages/searching/linearSearch.jsx new file mode 100644 index 0000000..a41391b --- /dev/null +++ b/src/pages/searching/linearSearch.jsx @@ -0,0 +1,132 @@ +import React, { useState } from "react"; +import { Toaster, toast } from "react-hot-toast"; +import LinearSearchVisualizer from "../../components/searching/LinearSearchVisualizer"; +import { linearSearch } from "../../algorithms/searching/linearSearch"; + + +export default function LinearSearch() { + const [array, setArray] = useState([]); + const [input, setInput] = useState(""); + + // --- SEARCH STATES --- + const [target, setTarget] = useState(null); + const [highlightIndex, setHighlightIndex] = useState(null); + const [foundIndex, setFoundIndex] = useState(null); + // --------------------- + + const [isRunning, setIsRunning] = useState(false); + + const handleStart = async () => { + if (isRunning || array.length === 0 || isNaN(parseInt(target))) { + toast.error("Please ensure the array and target are valid."); + return; + } + + setIsRunning(true); + setHighlightIndex(null); + setFoundIndex(null); + + const targetNumber = parseInt(target); + + // Pass the array AND the target to the generator + const gen = linearSearch(array, targetNumber); + + for (let step of gen) { + // Update search-specific states + setHighlightIndex(step.highlightIndex); + setFoundIndex(step.foundIndex); + + if (step.message) { + if (step.foundIndex !== null) { + toast.success(step.message); + } else { + toast.error(step.message); + } + } + + // Wait for 500ms for visualization (adjust this speed later) + await new Promise((r) => setTimeout(r, 500)); + } + + setIsRunning(false); + }; + + const handleReset = () => { + setArray([]); + setInput(""); + setTarget(50); // Reset target input + setHighlightIndex(null); + setFoundIndex(null); + setIsRunning(false); + }; + + const handleInput = (e) => { + setInput(e.target.value); + const numbers = e.target.value + .split(",") + .map((n) => parseInt(n.trim())) + .filter((n) => !isNaN(n)); + setArray(numbers); + }; + + const handleTargetChange = (e) => { + setTarget(e.target.value); + }; + + return ( +
+ +

+ Linear Search Visualizer +

+ + {/* INPUTS: ARRAY AND TARGET */} +
+ + +
+ +
+ + +
+ +
+ {/* USE THE NEW VISUALIZER AND PASS SEARCH STATES */} + +
+ +
+ ); +} \ No newline at end of file diff --git a/src/pages/searching/searchingPage.jsx b/src/pages/searching/searchingPage.jsx new file mode 100644 index 0000000..6f3d602 --- /dev/null +++ b/src/pages/searching/searchingPage.jsx @@ -0,0 +1,61 @@ +// src/pages/SortingPage.jsx +import React, { useState } from "react"; +import LinearSearch from "./linearSearch"; + +export default function SortingPage() { + const [selectedAlgo, setSelectedAlgo] = useState(""); + + const renderAlgorithm = () => { + switch (selectedAlgo) { + case "LinearSearch": + return ; + + default: + return ( +
+ Select an algorithm to visualize 👆 +
+ ); + } + }; + + return ( +
+ {/* Left Sidebar */} +
+

+ Searching Panel +

+ + + + + + + + ← Back to Home + +
+ + {/* Right Visualization Area */} +
+ {renderAlgorithm()} +
+
+ ); +}