From 0df17d0660976563ad2f04014147acab31c74ef3 Mon Sep 17 00:00:00 2001 From: Sohan Rout Date: Sun, 2 Aug 2026 14:55:42 +0530 Subject: [PATCH] Feat : added updates to circular linked list --- .../linkedList/types/circular/animation.jsx | 62 +---- .../linkedList/types/circular/content.jsx | 260 +++++++++++------- .../linkedList/types/circular/page.jsx | 61 ++++ .../linkedList/types/circular/quiz.jsx | 1 + .../searching/binarysearch/page.jsx | 3 +- lib/modulesMap.js | 1 + 6 files changed, 233 insertions(+), 155 deletions(-) diff --git a/app/visualizer/linkedList/types/circular/animation.jsx b/app/visualizer/linkedList/types/circular/animation.jsx index 150d933..b96b9d4 100755 --- a/app/visualizer/linkedList/types/circular/animation.jsx +++ b/app/visualizer/linkedList/types/circular/animation.jsx @@ -1,14 +1,7 @@ 'use client'; import React, { useState, useRef, useEffect } from 'react'; import { gsap } from 'gsap'; -import Footer from '@/app/components/footer'; import ResetButton from '@/app/components/ui/resetButton'; -import ExploreOther from '@/app/components/ui/exploreOther'; -import Content from "@/app/visualizer/linkedList/types/circular/content"; -import Quiz from '@/app/visualizer/linkedList/types/circular/quiz'; -import CodeBlock from "@/app/visualizer/linkedList/types/circular/codeBlock"; -import BackToTop from '@/app/components/ui/backtotop'; -import GoBackButton from "@/app/components/ui/goback"; const CircularLinkedListVisualizer = () => { const [inputValue, setInputValue] = useState(''); @@ -92,25 +85,13 @@ const CircularLinkedListVisualizer = () => { }, [list]); return ( -
- {/* go back block here */} -
- -
- - {/* main logic here */} -

- Circular Linked List -

-
-

Visualize Circular Linked List Operations

{/* Input Form */} -
+
- -

- Test Your Knowledge before moving forward! -

- - - - - -
- -
-
); }; diff --git a/app/visualizer/linkedList/types/circular/content.jsx b/app/visualizer/linkedList/types/circular/content.jsx index 0ab9056..4d74afb 100755 --- a/app/visualizer/linkedList/types/circular/content.jsx +++ b/app/visualizer/linkedList/types/circular/content.jsx @@ -2,6 +2,113 @@ import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; import InContentAd from "@/app/components/ads/InContentAd"; + +const LoopDiagram = ({ nodes, keyPrefix }) => { + const size = 220; + const topPadding = 24; + const height = size + topPadding; + const centerX = size / 2; + const centerY = size / 2 + topPadding; + const radius = 70; + const nodeRadius = 26; + + const positions = nodes.map((_, i) => { + const angle = (-90 + i * (360 / nodes.length)) * (Math.PI / 180); + return { + x: centerX + radius * Math.cos(angle), + y: centerY + radius * Math.sin(angle), + }; + }); + + return ( + + + + + + + + {positions.map((pos, i) => { + const next = positions[(i + 1) % positions.length]; + const dx = next.x - pos.x; + const dy = next.y - pos.y; + const dist = Math.sqrt(dx * dx + dy * dy) || 1; + const ux = dx / dist; + const uy = dy / dist; + const startX = pos.x + ux * (nodeRadius + 2); + const startY = pos.y + uy * (nodeRadius + 2); + const endX = next.x - ux * (nodeRadius + 6); + const endY = next.y - uy * (nodeRadius + 6); + const midX = (startX + endX) / 2; + const midY = (startY + endY) / 2; + const controlX = midX + (centerX - midX) * 0.35; + const controlY = midY + (centerY - midY) * 0.35; + + return ( + + ); + })} + + {positions.map((pos, i) => ( + + + + + {nodes[i]} + + + ))} + + {positions[0] && ( + + head + + )} + + ); +}; + const Content = () => { const [theme, setTheme] = useState("light"); @@ -39,21 +146,21 @@ const Content = () => { ]; const insertionSteps = [ - { step: "1. Create new node with data" }, - { step: "2. If list is empty, set head and tail to new node" }, - { step: "3. Make new node point to itself (circular reference)" }, - { step: "4. For non-empty list, set new node's next to current head" }, - { step: "5. Update tail's next pointer to new node" }, - { step: "6. Move head pointer to new node" }, + { step: "Create new node with data" }, + { step: "If list is empty, set head and tail to new node" }, + { step: "Make new node point to itself (circular reference)" }, + { step: "For non-empty list, set new node's next to current head" }, + { step: "Update tail's next pointer to new node" }, + { step: "Move head pointer to new node" }, ]; const deletionSteps = [ - { step: "1. Check if list is empty" }, - { step: "2. If single node exists, set head and tail to null" }, - { step: "3. For head deletion, update head to head.next" }, - { step: "4. Update tail's next pointer to new head" }, - { step: "5. For middle deletion, find node and update previous node's pointer" }, - { step: "6. Handle special case when deleting last node" }, + { step: "Check if list is empty" }, + { step: "If single node exists, set head and tail to null" }, + { step: "For head deletion, update head to head.next" }, + { step: "Update tail's next pointer to new head" }, + { step: "For middle deletion, find node and update previous node's pointer" }, + { step: "Handle special case when deleting last node" }, ]; const prosCons = [ @@ -113,7 +220,7 @@ const Content = () => { ))}

- Key Property: The last node's next pointer always points back to the first node, creating a continuous loop. + Key Property: The last node{"\'"}s next pointer always points back to the first node, creating a continuous loop.

@@ -147,35 +254,24 @@ const Content = () => { {/* Insertion Process */}

Insertion Process

-
-
-
    - {insertionSteps.map((step, index) => ( -
  1. - {step.step} -
  2. - ))} -
-
-
-
-
-
-
head
-
[A]
-
[B]
-
-
Existing circular list
-
-
↓ Insert X at head ↓
-
-
-
head
-
[X]
-
[A]
-
[B]
-
-
+
    + {insertionSteps.map((step, index) => ( +
  1. + {step.step} +
  2. + ))} +
+ +
+
+
+ +
Existing circular list
+
+
+
+ +
After inserting X at head
@@ -184,35 +280,24 @@ const Content = () => { {/* Deletion Process */}

Deletion Process

-
-
-
    - {deletionSteps.map((step, index) => ( -
  1. - {step.step} -
  2. - ))} -
-
-
-
-
-
-
head
-
[X]
-
[A]
-
[B]
-
-
Current circular list
-
-
↓ Delete X (head) ↓
-
-
-
head
-
[A]
-
[B]
-
-
+
    + {deletionSteps.map((step, index) => ( +
  1. + {step.step} +
  2. + ))} +
+ +
+
+
+ +
Current circular list
+
+
+
+ +
After deleting X (head)
@@ -266,39 +351,6 @@ const Content = () => {
- {/* Pros and Cons */} -
-

Pros and Cons

-
-
-

Advantages

-
    - {prosCons.filter(item => item.type === "pro").map((item, index) => ( -
  • - - - - {item.point} -
  • - ))} -
-
-
-

Limitations

-
    - {prosCons.filter(item => item.type === "con").map((item, index) => ( -
  • - - - - {item.point} -
  • - ))} -
-
-
-
- {/* Applications */}

Applications

diff --git a/app/visualizer/linkedList/types/circular/page.jsx b/app/visualizer/linkedList/types/circular/page.jsx index cadf675..166c7ff 100755 --- a/app/visualizer/linkedList/types/circular/page.jsx +++ b/app/visualizer/linkedList/types/circular/page.jsx @@ -3,6 +3,12 @@ import Navbar from "@/app/components/navbarinner"; import ModuleHeader from "@/app/components/modules/Header"; import Footer from "@/app/components/footer"; import BackToTopButton from "@/app/components/ui/backtotop"; +import Content from "./content"; +import Quiz from "./quiz"; +import Code from "./codeBlock"; +import ModuleCard from "@/app/components/ui/ModuleCard"; +import { MODULE_MAPS } from "@/lib/modulesMap"; +import ExploreOther from "@/app/components/ui/exploreOther"; export const metadata = { title: 'Circular Linked List Algorithm | Interactive Learning & Step-by-Step Animation', @@ -22,8 +28,32 @@ export const metadata = { 'DSA Quiz Circular Linked List', 'Circular Linked List Implementation Code', 'DSA Learning Platform', + 'Circular Linked List in JavaScript', + 'Circular Linked List in C', + 'Circular Linked List in Python', + 'Circular Linked List in Java', + 'Singly Circular Linked List', + 'Doubly Circular Linked List', + 'Circular Linked List vs Linear Linked List', + 'Circular Linked List Time Complexity', + 'Round Robin Scheduling Data Structure', + 'Circular Buffer Implementation', + 'Circular Linked List Interview Questions', + 'Circular Linked List Code Examples', + 'Interactive DSA Visualizer', ], robots: 'index, follow', + openGraph: { + images: [ + { + // TODO: swap in a dedicated /og/linkedList/circular.png once it's ready; using the site-wide OG image as a placeholder for now. + url: '/og.png', + width: 1200, + height: 630, + alt: 'Circular Linked List Visualization', + }, + ], + }, }; export default function Page() { const paths = [ @@ -41,11 +71,42 @@ export default function Page() {
+
+ +
+

+ Test Your Knowledge before moving forward! +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/app/visualizer/linkedList/types/circular/quiz.jsx b/app/visualizer/linkedList/types/circular/quiz.jsx index 34f7c15..7414870 100755 --- a/app/visualizer/linkedList/types/circular/quiz.jsx +++ b/app/visualizer/linkedList/types/circular/quiz.jsx @@ -1,3 +1,4 @@ +"use client"; import React, { useState } from 'react'; import { FaCheck, FaTimes, FaArrowRight, FaArrowLeft, FaInfoCircle, FaRedo, FaTrophy, FaStar, FaAward } from 'react-icons/fa'; import { motion, AnimatePresence } from 'framer-motion'; diff --git a/app/visualizer/searching/binarysearch/page.jsx b/app/visualizer/searching/binarysearch/page.jsx index 9351568..485ccfd 100755 --- a/app/visualizer/searching/binarysearch/page.jsx +++ b/app/visualizer/searching/binarysearch/page.jsx @@ -67,7 +67,8 @@ export default function Page() {
- + +
diff --git a/lib/modulesMap.js b/lib/modulesMap.js index 535882f..782205b 100755 --- a/lib/modulesMap.js +++ b/lib/modulesMap.js @@ -25,4 +25,5 @@ export const MODULE_MAPS = { queueArray : "06ec481b-d6a7-46e9-8a74-16031d298734", queueLinkedList : "b217f8ad-38e3-4f55-b066-2f5f67d7ea36", singlyLinkedList : "c2a06c17-8ecc-49e7-a17b-aaf75544e782", + circularLinkedList : "202bc165-82de-4fb5-bb2a-ec3b4dec60c7", } \ No newline at end of file