diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 3a115db..cd0d326 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -7,6 +7,7 @@ import DoublyLinkedList from "./pages/DoublyLinkedList"; import HashTable from "./pages/HashTable"; import Queue from "./pages/Queue"; import Stack from "./pages/Stack"; +import BinarySearchTree from "./pages/BinarySearchTree"; function AppRouter() { return ( @@ -19,6 +20,7 @@ function AppRouter() { } /> } /> } /> + } /> ); diff --git a/src/components/DSPlaygrounds/BinarySearchTreePG.tsx b/src/components/DSPlaygrounds/BinarySearchTreePG.tsx new file mode 100644 index 0000000..2e815e8 --- /dev/null +++ b/src/components/DSPlaygrounds/BinarySearchTreePG.tsx @@ -0,0 +1,135 @@ +import { useState } from "react"; +import { PlaygroundProps } from "../../entities"; +import { Link } from "react-router-dom"; +import PencilIcon from "../Icons/PencilIcon"; +import map from "../../data/data-structures"; + +interface TreeNode { + value: number; + left: TreeNode | null; + right: TreeNode | null; +} + +function BinarySearchTreePG({ className }: PlaygroundProps) { + const ds = map.get("binary-search-tree")!; + const [root, setRoot] = useState(null); + const [inputValue, setInputValue] = useState(""); + const [errorMessage, setErrorMessage] = useState(""); + + const insert = (node: TreeNode | null, value: number): TreeNode => { + if (node === null) { + return { value, left: null, right: null }; + } + + if (value < node.value) { + return { ...node, left: insert(node.left, value) }; + } else if (value > node.value) { + return { ...node, right: insert(node.right, value) }; + } + + return node; + }; + + const handleInsert = () => { + const value = parseInt(inputValue); + if (isNaN(value)) { + setErrorMessage("Please enter a valid number"); + return; + } + + setRoot((prevRoot) => insert(prevRoot, value)); + setInputValue(""); + setErrorMessage(""); + }; + + const findMin = (node: TreeNode): TreeNode => { + let curr = node; + while (curr.left !== null) { + curr = curr.left; + } + return curr; + }; + + const deleteNode = ( + node: TreeNode | null, + value: number + ): TreeNode | null => { + if (node === null) return null; + + if (value < node.value) { + return { ...node, left: deleteNode(node.left, value) }; + } else if (value > node.value) { + return { ...node, right: deleteNode(node.right, value) }; + } + + // Node to delete found + else { + // Case 1 - Leaf Node + if (node.left === null && node.right === null) { + return null; + } + + // Case 2 - Node with 1 child + if (node.left === null) { + return node.right; + } + if (node.right === null) { + return node.left; + } + + // Case 3 - Node with 2 children + const minNode = findMin(node.right); + return { + ...node, + value: minNode.value, + right: deleteNode(node.right, minNode.value), + }; + } + }; + + const handleDelete = () => { + const value = parseInt(inputValue); + if (isNaN(value)) { + setErrorMessage("Please enter a valid number"); + return; + } + setRoot((prevRoot) => deleteNode(prevRoot, value)); + setInputValue(""); + setErrorMessage(""); + }; + + return ( +
+
+
+ setInputValue(e.target.value)} + className="input input-bordered" + placeholder="Enter a number" + /> + + +
+ +

Notes

+ +
+ + {/* Visualization Window - To be implemented */} +
+ {/* Tree visualization will go here */} +
+ + {/* Error Messages */} + {errorMessage &&
{errorMessage}
} +
+ ); +} + +export default BinarySearchTreePG; diff --git a/src/data/data-structures.ts b/src/data/data-structures.ts index c7e0218..9fed1c2 100644 --- a/src/data/data-structures.ts +++ b/src/data/data-structures.ts @@ -5,7 +5,7 @@ export const dataStructures: DataStructureKV[] = [ "dynamic-array", { name: "Dynamic Array", - description: "Resizable arrays with dynamic capacity.", + description: "Resizable arrays with dynamic capacity", icon: "🪟", category: "Arrays/Strings", difficulty: "Beginner", @@ -16,7 +16,7 @@ export const dataStructures: DataStructureKV[] = [ "singly-linked-list", { name: "Singly Linked List", - description: "Linear collection with nodes linked in sequence.", + description: "Linear collection with nodes linked in sequence", icon: "🔜", category: "Linked Lists", difficulty: "Beginner", @@ -27,7 +27,7 @@ export const dataStructures: DataStructureKV[] = [ "doubly-linked-list", { name: "Doubly Linked List", - description: "Nodes linked bi-directionally for efficient traversal.", + description: "Nodes linked bi-directionally for efficient traversal", icon: "🔛", category: "Linked Lists", difficulty: "Beginner", @@ -38,7 +38,7 @@ export const dataStructures: DataStructureKV[] = [ "hash-table", { name: "Hash Table", - description: "Key-value pairs for efficient data retrieval.", + description: "Key-value pairs for efficient data retrieval", icon: "🧮", category: "Hashing", difficulty: "Beginner", @@ -70,12 +70,25 @@ export const dataStructures: DataStructureKV[] = [ }, ], [ - "binary-search", + "binary-search-tree", { - name: "Binary Search", - description: "", - icon: "⏱️", - category: "", + name: "Binary Search Tree", + description: + "A binary tree where left child < parent < right child for all nodes", + icon: "🌲", + category: "Tree", + difficulty: "Intermediate", + notesUrl: "", + }, + ], + [ + "graph", + { + name: "Graph", + description: + "A non-linear data structure consisting of vertices (or nodes) connected by edges", + icon: "🕸️", + category: "Graph", difficulty: "Intermediate", notesUrl: "", }, diff --git a/src/pages/BinarySearch.tsx b/src/pages/BinarySearch.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/BinarySearchTree.tsx b/src/pages/BinarySearchTree.tsx new file mode 100644 index 0000000..bee136b --- /dev/null +++ b/src/pages/BinarySearchTree.tsx @@ -0,0 +1,21 @@ +import map from "../data/data-structures"; +import Heading from "../components/Heading"; +import BinarySearchTreePG from "../components/DSPlaygrounds/BinarySearchTreePG"; + +function BinarySearchTree() { + const binarySearchTree = map.get("binary-search-tree")!; + + return ( +
+
+ {/* Heading */} + + + {/* Playground */} + +
+
+ ); +} + +export default BinarySearchTree;