From 4800f8c5f85d25341a3b265c17f33e8e16769000 Mon Sep 17 00:00:00 2001 From: Sohan Rout Date: Mon, 3 Aug 2026 19:54:36 +0530 Subject: [PATCH 1/3] Feat : added heap sort and huffman --- app/visualizer/page.jsx | 6 +- .../lowest-common-ancestor/page.jsx | 1 + .../serialize-deserialize/animation.jsx | 455 ++++++++++++++++++ .../algorithms/serialize-deserialize/code.js | 190 ++++++++ .../serialize-deserialize/content.jsx | 223 +++++++++ .../algorithms/serialize-deserialize/page.jsx | 115 +++++ .../algorithms/serialize-deserialize/quiz.jsx | 379 +++++++++++++++ .../trees/algorithms/tree-diameter/page.jsx | 1 + .../algorithms/tree-isomorphism/page.jsx | 1 + .../applications/heap-sort/animation.jsx | 400 +++++++++++++++ .../trees/applications/heap-sort/code.js | 161 +++++++ .../trees/applications/heap-sort/content.jsx | 234 +++++++++ .../trees/applications/heap-sort/page.jsx | 111 +++++ .../trees/applications/heap-sort/quiz.jsx | 384 +++++++++++++++ .../applications/huffman-coding/animation.jsx | 418 ++++++++++++++++ .../trees/applications/huffman-coding/code.js | 208 ++++++++ .../applications/huffman-coding/content.jsx | 222 +++++++++ .../applications/huffman-coding/page.jsx | 111 +++++ .../applications/huffman-coding/quiz.jsx | 379 +++++++++++++++ lib/modulesMap.js | 3 + 20 files changed, 3999 insertions(+), 3 deletions(-) create mode 100755 app/visualizer/trees/algorithms/serialize-deserialize/animation.jsx create mode 100755 app/visualizer/trees/algorithms/serialize-deserialize/code.js create mode 100755 app/visualizer/trees/algorithms/serialize-deserialize/content.jsx create mode 100755 app/visualizer/trees/algorithms/serialize-deserialize/page.jsx create mode 100755 app/visualizer/trees/algorithms/serialize-deserialize/quiz.jsx create mode 100755 app/visualizer/trees/applications/heap-sort/animation.jsx create mode 100755 app/visualizer/trees/applications/heap-sort/code.js create mode 100755 app/visualizer/trees/applications/heap-sort/content.jsx create mode 100755 app/visualizer/trees/applications/heap-sort/page.jsx create mode 100755 app/visualizer/trees/applications/heap-sort/quiz.jsx create mode 100755 app/visualizer/trees/applications/huffman-coding/animation.jsx create mode 100755 app/visualizer/trees/applications/huffman-coding/code.js create mode 100755 app/visualizer/trees/applications/huffman-coding/content.jsx create mode 100755 app/visualizer/trees/applications/huffman-coding/page.jsx create mode 100755 app/visualizer/trees/applications/huffman-coding/quiz.jsx diff --git a/app/visualizer/page.jsx b/app/visualizer/page.jsx index ef20c25..8cb2696 100755 --- a/app/visualizer/page.jsx +++ b/app/visualizer/page.jsx @@ -411,7 +411,7 @@ const sections = [ }, { name: "Serialize/Deserialize", - path: "/visualizer/trees/algorithms/serialization", + path: "/visualizer/trees/algorithms/serialize-deserialize", }, ], }, @@ -420,11 +420,11 @@ const sections = [ items: [ { name: "Heap Sort", - path: "/visualizer/trees/applications/heapsort", + path: "/visualizer/trees/applications/heap-sort", }, { name: "Huffman Coding", - path: "/visualizer/trees/applications/huffman", + path: "/visualizer/trees/applications/huffman-coding", }, { name: "Decision Trees", diff --git a/app/visualizer/trees/algorithms/lowest-common-ancestor/page.jsx b/app/visualizer/trees/algorithms/lowest-common-ancestor/page.jsx index 48a10f2..f747a44 100755 --- a/app/visualizer/trees/algorithms/lowest-common-ancestor/page.jsx +++ b/app/visualizer/trees/algorithms/lowest-common-ancestor/page.jsx @@ -102,6 +102,7 @@ export default function Page() { links={[ { text: "Tree Diameter", url: "./tree-diameter" }, { text: "Tree Isomorphism", url: "./tree-isomorphism" }, + { text: "Serialize/Deserialize", url: "./serialize-deserialize" }, { text: "BST Searching", url: "../bst/searching" }, { text: "BST Insertion", url: "../bst/insertion" }, { text: "AVL Balancing", url: "../bst/avl" }, diff --git a/app/visualizer/trees/algorithms/serialize-deserialize/animation.jsx b/app/visualizer/trees/algorithms/serialize-deserialize/animation.jsx new file mode 100755 index 0000000..40b27ab --- /dev/null +++ b/app/visualizer/trees/algorithms/serialize-deserialize/animation.jsx @@ -0,0 +1,455 @@ +"use client"; +import React, { useState } from "react"; +import { gsap } from "gsap"; +import { Plus, ArrowDownToLine, ArrowUpFromLine, Shuffle, RotateCcw } from "lucide-react"; + +class TreeNode { + constructor(value) { + this.value = value; + this.left = null; + this.right = null; + } +} + +const insertNode = (node, value) => { + if (!node) return new TreeNode(value); + if (value < node.value) node.left = insertNode(node.left, value); + else if (value > node.value) node.right = insertNode(node.right, value); + return node; +}; + +// Preorder traversal that records a "null" token for every empty child — +// that's what lets deserialization know exactly where each subtree ends. +const serializeWithSteps = (root) => { + const steps = []; + const visit = (node) => { + if (!node) { + steps.push({ token: "null", value: null }); + return; + } + steps.push({ token: String(node.value), value: node.value }); + visit(node.left); + visit(node.right); + }; + visit(root); + return steps; +}; + +// Consumes tokens in the same preorder sequence they were written in: +// read a token, and if it isn't "null", build a node and recurse for its +// left then right child before returning control to the parent call. +const deserializeWithSteps = (tokens) => { + const steps = []; + let i = 0; + const build = () => { + const token = tokens[i++]; + if (token === undefined || token === "null") { + steps.push({ token: "null", value: null }); + return null; + } + const value = Number(token); + steps.push({ token, value }); + const node = new TreeNode(value); + node.left = build(); + node.right = build(); + return node; + }; + const root = build(); + return { root, steps }; +}; + +const NODE_RADIUS = 18; +const LEVEL_HEIGHT = 62; + +const layoutTree = (node, depth = 0, x = 150, y = 28, nodes = [], edges = []) => { + if (!node) return { nodes, edges }; + const isLeaf = !node.left && !node.right; + const xOffset = Math.max(20, 90 / (depth + 1)); + + nodes.push({ value: node.value, x, y, depth, isLeaf, isRoot: depth === 0 }); + + if (node.left) { + const leftX = x - xOffset; + const leftY = y + LEVEL_HEIGHT; + edges.push({ x1: x, y1: y + NODE_RADIUS - 2, x2: leftX, y2: leftY - NODE_RADIUS + 2, parentValue: node.value, childValue: node.left.value }); + layoutTree(node.left, depth + 1, leftX, leftY, nodes, edges); + } + if (node.right) { + const rightX = x + xOffset; + const rightY = y + LEVEL_HEIGHT; + edges.push({ x1: x, y1: y + NODE_RADIUS - 2, x2: rightX, y2: rightY - NODE_RADIUS + 2, parentValue: node.value, childValue: node.right.value }); + layoutTree(node.right, depth + 1, rightX, rightY, nodes, edges); + } + + return { nodes, edges }; +}; + +const getSvgDimensions = (nodes) => { + if (nodes.length === 0) return { width: 320, height: 180 }; + const xValues = nodes.map((n) => n.x); + const yValues = nodes.map((n) => n.y); + const padding = 32; + return { + width: Math.max(320, Math.max(...xValues) - Math.min(...xValues) + padding * 2), + height: Math.max(180, Math.max(...yValues) + padding * 2), + }; +}; + +const TreePanel = ({ title, nodes, edges, visited, ringColor, visibleSet, gradId, emptyText }) => { + const dims = getSvgDimensions(nodes); + const isVisible = (value) => !visibleSet || visibleSet.has(value); + const animateDropIn = (el) => { + if (!el || el.dataset.animated) return; + el.dataset.animated = "true"; + gsap.fromTo(el, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, duration: 0.4, ease: "back.out(1.7)" }); + }; + + return ( +
+
{title}
+
+ {nodes.length > 0 ? ( + + + + + + + + + + + + + {edges.map((edge, i) => { + if (!isVisible(edge.parentValue) || !isVisible(edge.childValue)) return null; + const midY = (edge.y1 + edge.y2) / 2; + return ( + + ); + })} + + {nodes.map((node, i) => { + if (!isVisible(node.value)) return null; + const isActive = visited && visited.has(node.value); + return ( + + {node.isRoot && ( + + )} + {isActive && ( + + )} + + + {node.value} + + + ); + })} + + ) : ( +
+ {emptyText} +
+ )} +
+
+ ); +}; + +const STEP_DELAY = 500; + +const SerializeDeserializeVisualizer = () => { + const [sourceRoot, setSourceRoot] = useState(null); + const [inputValue, setInputValue] = useState(""); + const [visitedSource, setVisitedSource] = useState(new Set()); + const [serializedDisplay, setSerializedDisplay] = useState(""); + const [serializedInput, setSerializedInput] = useState(""); + + const [reconstructedRoot, setReconstructedRoot] = useState(null); + const [revealedRecon, setRevealedRecon] = useState(new Set()); + + const [message, setMessage] = useState("Build a tree, then serialize it"); + const [busy, setBusy] = useState(false); + + const handleInsert = () => { + const value = parseInt(inputValue, 10); + if (Number.isNaN(value)) { + setMessage("Please enter a valid number"); + return; + } + if (busy) return; + setSourceRoot((prev) => insertNode(prev ? structuredClone(prev) : null, value)); + setMessage(`Inserted ${value}`); + setInputValue(""); + setVisitedSource(new Set()); + setSerializedDisplay(""); + setSerializedInput(""); + setReconstructedRoot(null); + setRevealedRecon(new Set()); + }; + + const generateRandomTree = () => { + if (busy) return; + const size = Math.floor(Math.random() * 5) + 6; + const values = Array.from({ length: size }, () => Math.floor(Math.random() * 100) + 1); + let newRoot = null; + values.forEach((v) => { + newRoot = insertNode(newRoot, v); + }); + setSourceRoot(newRoot); + setMessage(`Generated a tree with ${size} random inserts`); + setVisitedSource(new Set()); + setSerializedDisplay(""); + setSerializedInput(""); + setReconstructedRoot(null); + setRevealedRecon(new Set()); + }; + + const reset = () => { + if (busy) return; + setSourceRoot(null); + setInputValue(""); + setVisitedSource(new Set()); + setSerializedDisplay(""); + setSerializedInput(""); + setReconstructedRoot(null); + setRevealedRecon(new Set()); + setMessage("Build a tree, then serialize it"); + }; + + const handleSerialize = () => { + if (busy || !sourceRoot) return; + const steps = serializeWithSteps(sourceRoot); + setBusy(true); + setVisitedSource(new Set()); + setSerializedDisplay(""); + setReconstructedRoot(null); + setRevealedRecon(new Set()); + + let i = 0; + const acc = []; + const reveal = () => { + const s = steps[i]; + acc.push(s.token); + setSerializedDisplay(acc.join(",")); + if (s.value !== null) { + setVisitedSource((prev) => new Set(prev).add(s.value)); + setMessage(`Visited ${s.value} — appended to the output string`); + } else { + setMessage("Hit an empty child — appended a null marker"); + } + i++; + if (i < steps.length) { + setTimeout(reveal, STEP_DELAY); + } else { + setTimeout(() => { + setSerializedInput(acc.join(",")); + setMessage("Serialization complete — this string fully encodes the tree's shape and values"); + setBusy(false); + }, STEP_DELAY); + } + }; + reveal(); + }; + + const handleDeserialize = () => { + if (busy || !serializedInput.trim()) { + setMessage("Serialize a tree first, or type a comma-separated preorder string"); + return; + } + const tokens = serializedInput + .split(",") + .map((t) => t.trim()) + .filter((t) => t.length > 0); + const { root, steps } = deserializeWithSteps(tokens); + if (!root) { + setMessage("That string decodes to an empty tree"); + return; + } + + setBusy(true); + setReconstructedRoot(root); + setRevealedRecon(new Set()); + + let i = 0; + const reveal = () => { + const s = steps[i]; + if (s.value !== null) { + setRevealedRecon((prev) => new Set(prev).add(s.value)); + setMessage(`Read token "${s.token}" — created node ${s.value}`); + } else { + setMessage(`Read token "null" — no node here`); + } + i++; + if (i < steps.length) { + setTimeout(reveal, STEP_DELAY); + } else { + setTimeout(() => { + setMessage("Deserialization complete — the tree has been fully reconstructed from the string"); + setBusy(false); + }, STEP_DELAY); + } + }; + reveal(); + }; + + const { nodes: sourceNodes, edges: sourceEdges } = sourceRoot ? layoutTree(sourceRoot) : { nodes: [], edges: [] }; + const { nodes: reconNodes, edges: reconEdges } = reconstructedRoot ? layoutTree(reconstructedRoot) : { nodes: [], edges: [] }; + + return ( +
+

+ Encode a tree into a string, then rebuild it back into an identical tree +

+ +
+ {/* Controls */} +
+
+ setInputValue(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleInsert()} + placeholder="Enter a number" + disabled={busy} + className="flex-1 min-w-0 px-3 py-2 text-sm rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-neutral-900 text-gray-800 dark:text-gray-100 placeholder:text-gray-400 dark:placeholder:text-gray-500 outline-none focus:ring-2 focus:ring-blue-500/40 focus:border-blue-500 transition disabled:opacity-50" + /> + +
+ +
+ + +
+ +
+ + +
+ + setSerializedInput(e.target.value)} + placeholder="Serialized string (e.g. 8,3,1,null,null,6,null,null,10,null,null)" + disabled={busy} + className="w-full px-3 py-2 text-sm font-mono rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-neutral-900 text-gray-800 dark:text-gray-100 placeholder:text-gray-400 dark:placeholder:text-gray-500 outline-none focus:ring-2 focus:ring-blue-500/40 focus:border-blue-500 transition disabled:opacity-50" + /> +
+ + {/* Message */} +
+ {message} +
+ + {/* Live serialized string */} + {serializedDisplay && ( +
+ {serializedDisplay} +
+ )} + + {/* Trees */} +
+ + +
+ +
+ + + Internal node + + + + Leaf node + + + + Root + + + + Visited during serialize + + + + Created during deserialize + +
+
+
+ ); +}; + +export default SerializeDeserializeVisualizer; diff --git a/app/visualizer/trees/algorithms/serialize-deserialize/code.js b/app/visualizer/trees/algorithms/serialize-deserialize/code.js new file mode 100755 index 0000000..8500326 --- /dev/null +++ b/app/visualizer/trees/algorithms/serialize-deserialize/code.js @@ -0,0 +1,190 @@ +const codeExamples = { + javascript: `// Binary tree node +class TreeNode { + constructor(value) { + this.value = value; + this.left = null; + this.right = null; + } +} + +// Preorder traversal, writing a "null" marker for every empty child so the +// shape of the tree — not just its values — is fully recoverable. +function serialize(root) { + const tokens = []; + + function visit(node) { + if (node === null) { + tokens.push("null"); + return; + } + tokens.push(String(node.value)); + visit(node.left); + visit(node.right); + } + + visit(root); + return tokens.join(","); +} + +// Reads tokens in the same preorder sequence they were written in. +function deserialize(data) { + const tokens = data.split(","); + let i = 0; + + function build() { + const token = tokens[i++]; + if (token === "null") return null; + + const node = new TreeNode(Number(token)); + node.left = build(); + node.right = build(); + return node; + } + + return build(); +} + +// Usage example +const encoded = serialize(root); // "8,3,1,null,null,6,null,null,10,null,null" +const rebuilt = deserialize(encoded); // structurally identical tree`, + + python: `# Binary tree node +class TreeNode: + def __init__(self, value): + self.value = value + self.left = None + self.right = None + +# Preorder traversal, writing a "null" marker for every empty child so the +# shape of the tree -- not just its values -- is fully recoverable. +def serialize(root): + tokens = [] + + def visit(node): + if node is None: + tokens.append("null") + return + tokens.append(str(node.value)) + visit(node.left) + visit(node.right) + + visit(root) + return ",".join(tokens) + +# Reads tokens in the same preorder sequence they were written in. +def deserialize(data): + tokens = data.split(",") + i = 0 + + def build(): + nonlocal i + token = tokens[i] + i += 1 + if token == "null": + return None + + node = TreeNode(int(token)) + node.left = build() + node.right = build() + return node + + return build() + +# Usage example +encoded = serialize(root) # "8,3,1,null,null,6,null,null,10,null,null" +rebuilt = deserialize(encoded) # structurally identical tree`, + + c: `#include +#include +#include + +typedef struct TreeNode { + int value; + struct TreeNode *left, *right; +} TreeNode; + +// Preorder traversal, writing a "null" marker for every empty child so the +// shape of the tree -- not just its values -- is fully recoverable. +void serialize(TreeNode* node, char* out) { + if (node == NULL) { + strcat(out, "null,"); + return; + } + char buf[16]; + sprintf(buf, "%d,", node->value); + strcat(out, buf); + serialize(node->left, out); + serialize(node->right, out); +} + +// Reads tokens in the same preorder sequence they were written in. +TreeNode* deserialize(char** tokens, int* index) { + char* token = tokens[*index]; + (*index)++; + if (strcmp(token, "null") == 0) return NULL; + + TreeNode* node = malloc(sizeof(TreeNode)); + node->value = atoi(token); + node->left = deserialize(tokens, index); + node->right = deserialize(tokens, index); + return node; +} + +int main() { + TreeNode* root = NULL; // build with insert() from BST Insertion + char encoded[256] = ""; + serialize(root, encoded); + printf("Encoded: %s\\n", encoded); + return 0; +}`, + + java: `import java.util.Arrays; +import java.util.Iterator; + +class TreeNode { + int value; + TreeNode left, right; + + TreeNode(int value) { + this.value = value; + } +} + +public class SerializeDeserialize { + + // Preorder traversal, writing a "null" marker for every empty child so + // the shape of the tree -- not just its values -- is fully recoverable. + static void serialize(TreeNode node, StringBuilder out) { + if (node == null) { + out.append("null,"); + return; + } + out.append(node.value).append(","); + serialize(node.left, out); + serialize(node.right, out); + } + + // Reads tokens in the same preorder sequence they were written in. + static TreeNode deserialize(Iterator tokens) { + String token = tokens.next(); + if (token.equals("null")) return null; + + TreeNode node = new TreeNode(Integer.parseInt(token)); + node.left = deserialize(tokens); + node.right = deserialize(tokens); + return node; + } + + public static void main(String[] args) { + TreeNode root = null; // build with insert() from BST Insertion + StringBuilder encoded = new StringBuilder(); + serialize(root, encoded); + System.out.println("Encoded: " + encoded); + + TreeNode rebuilt = deserialize(Arrays.asList(encoded.toString().split(",")).iterator()); + } +}`, +}; + +export default codeExamples; diff --git a/app/visualizer/trees/algorithms/serialize-deserialize/content.jsx b/app/visualizer/trees/algorithms/serialize-deserialize/content.jsx new file mode 100755 index 0000000..14c9936 --- /dev/null +++ b/app/visualizer/trees/algorithms/serialize-deserialize/content.jsx @@ -0,0 +1,223 @@ +"use client"; +import ComplexityGraph from "@/app/components/ui/graph"; +import { useTheme } from "@/app/contexts/ThemeContext"; +import DailyDSAEmbed from "@/app/components/ui/DailyDSAEmbed"; +import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; +import InContentAd from "@/app/components/ads/InContentAd"; +import { motion } from "framer-motion"; + +const WalkthroughDiagram = () => { + const nodes = [ + { id: "8", x: 110, y: 30 }, + { id: "3", x: 70, y: 80 }, + { id: "10", x: 150, y: 80 }, + { id: "1", x: 50, y: 130 }, + { id: "6", x: 90, y: 130 }, + ]; + const edges = [ + ["8", "3"], + ["8", "10"], + ["3", "1"], + ["3", "6"], + ]; + const byId = Object.fromEntries(nodes.map((n) => [n.id, n])); + + return ( + + {edges.map(([from, to], i) => ( + + ))} + + {nodes.map((n, i) => ( + + + + {n.id} + + + ))} + + + 8,3,1,null,null,6,null,null,10,null,null + + + ); +}; + +const Content = () => { + const { theme } = useTheme(); + + const paragraphs = [ + `Serialization converts a tree into a flat string (or byte stream) that can be saved to disk, sent over a network, or stored in a database. Deserialization is the reverse: reading that string back and rebuilding a tree that's structurally identical to the original — same shape, same values, same left/right placement everywhere.`, + `The tricky part isn't encoding the values — it's encoding the *shape*. A plain list of values loses information about which nodes were children of which, and where branches were missing. The standard fix is to explicitly record empty children with a marker (commonly "null" or "#") at every point a node is absent, using a preorder traversal: visit the node, then recurse left, then recurse right, writing a marker whenever a child doesn't exist.`, + `Because every empty spot is explicitly recorded, deserialization can rebuild the exact structure by reading tokens in that same preorder sequence: read one token — if it's a null marker, that subtree is empty; otherwise create a node from it, then recursively build its left child from the next tokens, then its right child. The reader never needs to guess where one subtree ends and another begins.`, + `This pattern shows up anywhere tree-shaped data needs to survive outside memory: saving a game's scene graph, sending a parsed expression tree between services, caching a computed index structure, or simply persisting any hierarchical data model to JSON or a file.`, + ]; + + const algorithm = [ + { + points: "Serialize (preorder, with null markers):", + subpoints: [ + "If the current node is empty, write a null marker and return", + "Otherwise, write the node's value", + "Recurse into the left child, then the right child", + ], + }, + { + points: "Deserialize (read tokens in the same order they were written):", + subpoints: [ + "Read the next token", + "If it's a null marker, this subtree is empty — return immediately", + "Otherwise, create a node from it, then recursively read its left child, then its right child", + ], + }, + ]; + + const complexity = [ + { points: "Time Complexity: O(n) for both serialize and deserialize — every node and every null marker is visited exactly once." }, + { points: "Space Complexity: O(n) for the output string, plus O(h) recursion stack for the traversal." }, + ]; + + return ( +
+
+ + +
+
+ {/* What is it */} +
+

+ + What is Serialization? +

+
+

+ {paragraphs[0]} +

+
+
+ + {/* How it works */} +
+

+ + How Does It Work? +

+
+

+ {paragraphs[1]} +

+
+
+

+ {paragraphs[2]} +

+
+ +
+ Preorder with null markers: visit 8, then 3, then 1 (both children null), back up, 6 (both children null), back up, 10 (both children null) +
+ +
+ + {/* Algorithm Steps */} +
+

+ + Algorithm Steps +

+
+
    + {algorithm.map((item, index) => ( +
  1. + {item.points} + {item.subpoints && ( +
      + {item.subpoints.map((subitem, subindex) => ( +
    • + {subitem} +
    • + ))} +
    + )} +
  2. + ))} +
+
+
+ + {/* Time Complexity */} +
+

+ + Time Complexity +

+
+
    + {complexity.map((item, index) => ( +
  • + + {item.points.split(":")[0]}: + + {item.points.split(":")[1]} +
  • + ))} +
+
+ +
+ n} + averageCase={(n) => n} + worstCase={(n) => n} + maxN={25} + /> +
+ + +
+ + {/* Additional Info */} +
+
+
+

+ {paragraphs[3]} +

+
+
+
+
+ + +
+ ); +}; + +export default Content; diff --git a/app/visualizer/trees/algorithms/serialize-deserialize/page.jsx b/app/visualizer/trees/algorithms/serialize-deserialize/page.jsx new file mode 100755 index 0000000..0e6a143 --- /dev/null +++ b/app/visualizer/trees/algorithms/serialize-deserialize/page.jsx @@ -0,0 +1,115 @@ +import Animation from "@/app/visualizer/trees/algorithms/serialize-deserialize/animation"; +import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTop from "@/app/components/ui/backtotop"; +import ExploreOther from "@/app/components/ui/exploreOther"; +import CodeBlock from "@/app/components/modules/CodeBlock"; +import codeExamples from "./code"; +import Quiz from "@/app/visualizer/trees/algorithms/serialize-deserialize/quiz"; +import Content from "@/app/visualizer/trees/algorithms/serialize-deserialize/content"; +import ModuleCard from "@/app/components/ui/ModuleCard"; +import { MODULE_MAPS } from "@/lib/modulesMap"; + +export const metadata = { + title: "Serialize and Deserialize a Binary Tree | Animation and Explanation", + description: + "Learn how to serialize a binary tree into a string using preorder traversal with null markers, and deserialize that string back into an identical tree, with an interactive visualizer, code examples in JavaScript, C, Python, and Java, and a quiz.", + keywords: [ + "Serialize and Deserialize Binary Tree", + "Tree Serialization", + "Binary Tree Serialization", + "Tree Serialization Algorithm", + "Binary Tree Serialization Algorithm", + "Tree Serialization Visualization", + "Binary Tree Serialization Visualization", + "Encode and Decode Binary Tree", + "Preorder Serialization", + "Serialize Binary Tree in JavaScript", + "Tree Serialization in JavaScript", + "Serialize Binary Tree in C", + "Tree Serialization in C", + "Serialize Binary Tree in Python", + "Tree Serialization in Python", + "Serialize Binary Tree in Java", + "Tree Serialization in Java", + "Tree Algorithms", + "DSA Trees", + "Learn Trees", + "Tree Quiz", + ], + robots: "index, follow", + openGraph: { + images: [ + { + url: "/og.png", + width: 1200, + height: 630, + alt: "Tree Serialization and Deserialization Visualization", + }, + ], + }, +}; + +export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Trees : Serialize/Deserialize", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+ + +
+ +
+ +
+ +
+

+ Test Your Knowledge before moving forward! +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ + +