<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Yazdun - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Yazdun - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:23:59 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/Yazdun/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Work with Queues in TypeScript ]]>
                </title>
                <description>
                    <![CDATA[ A queue is a collection of items arranged in a First-In-First-Out (FIFO) order. This means that the first item added is the first to be removed, much like a supermarket line where customers are served in the order they arrive. In this hands-on tutor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-work-with-queues-in-typescript/</link>
                <guid isPermaLink="false">6850919d88713cbf971283b0</guid>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yazdun ]]>
                </dc:creator>
                <pubDate>Mon, 16 Jun 2025 21:50:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750082265731/de8b778c-935d-4a38-a5ef-748896475327.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A queue is a collection of items arranged in a First-In-First-Out (FIFO) order. This means that the first item added is the first to be removed, much like a supermarket line where customers are served in the order they arrive.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741091206/42a62a3c-cf1b-4e7a-b8ce-4209e13f70d3.png" alt="Diagram illustrating a queue. Items are added to the back through &quot;enqueue&quot; and removed from the front through &quot;dequeue.&quot; Arrows show the flow into and out of a rectangular box representing the queue." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In this hands-on tutorial, you will learn how to implement queues in TypeScript using linked lists.</p>
<h2 id="heading-heres-what-well-cover">Here’s what we’ll cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-getting-started">Getting started</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-queues">What are Queues?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-linked-lists">What are Linked Lists?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-simple-queue">What is a Simple Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circular-queue">What is a Circular Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-double-ended-queue">What is a Double Ended Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-priority-queue">What is a Priority Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-queues-and-when-to-avoid-them">When to Use Queues (and When to Avoid Them)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li><p><strong>TypeScript:</strong> You need to know <a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/">TypeScript basics</a>, such as interfaces, types, and classes.</p>
</li>
<li><p><strong>Algorithm fundamentals:</strong> You need a basic understanding of data structures and algorithms. For example, you should be comfortable analyzing time and space complexity using <a target="_blank" href="https://www.freecodecamp.org/news/big-o-cheat-sheet-time-complexity-chart/">Big-O notation.</a></p>
</li>
<li><p><strong>Linked Lists Data Structure:</strong> It's important to have a solid understanding of linked lists before starting this tutorial. I wrote a detailed <a target="_blank" href="https://www.freecodecamp.org/news/how-to-code-linked-lists-with-typescript-handbook">linked list tutorial</a> that you can use to learn about this data structure.</p>
</li>
</ol>
<h2 id="heading-getting-started">Getting Started</h2>
<p>To get started with this tutorial, you’ll use a playground project that’s designed to help you implement queues and follow each step hands-on.</p>
<p>Clone the project from the <a target="_blank" href="https://github.com/Yazdun/fcc-queues">GitHub repository and code along</a> with the tutorial.</p>
<p>The project structure is as follows:</p>
<pre><code class="lang-plaintext">.
├── index.ts
├── examples
│   ├── 01-linked-list.ts
│   ├── 02-simple-queue.ts
│   ├── 03-circular-queue.ts
│   ├── 04-double-ended-queue.ts
│   └── 05-priority-queue.ts
└── playground
    ├── 01-linked-list.ts
    ├── 02-simple-queue.ts
    ├── 03-circular-queue.ts
    ├── 04-double-ended-queue.ts
    └── 05-priority-queue.ts
</code></pre>
<p>Throughout the tutorial, you will use the <code>playground</code> directory to implement and test your code.</p>
<p>The <code>examples</code> directory contains the final version of each implementation. If you get stuck, you can look at these solutions as a last resort!</p>
<h2 id="heading-what-are-queues">What Are Queues?</h2>
<p>A queue is a data structure that manages items in a first-in, first-out (FIFO) order, where the first item added is the first removed.</p>
<p>For example, imagine a printer handling jobs. If you send three documents to print, the printer processes them in the order they arrive. The first document prints first, then the second, and finally the third.</p>
<p>In programming, queues help manage tasks that need to happen in order, such as:</p>
<ul>
<li><p>A web server queues incoming requests to process them one by one.</p>
</li>
<li><p>A chat app queues messages to send them in the order they’re typed.</p>
</li>
<li><p>A navigation app queues locations to explore a map level by level. (Breadth-First Search)</p>
</li>
</ul>
<p>There are four types of queues in a data structure:</p>
<ul>
<li><p><strong>Simple Queue</strong>: Adds items to the back and removes them from the front in first-in, first-out (FIFO) order.</p>
</li>
<li><p><strong>Circular Queue</strong>: It is similar to a simple queue, except the last element is connected to the first.</p>
</li>
<li><p><strong>Double-Ended Queue (Deque)</strong>: Allows adding or removing items from both front and back, like a bus stop line where people join or leave either end.</p>
</li>
<li><p><strong>Priority Queue</strong>: Processes items based on priority, not arrival order. Like a delivery app processes VIP orders before regular ones.</p>
</li>
</ul>
<p>Each of these queues has a set of operations for managing their items. In this tutorial, you will learn about the following common and widely used operations:</p>
<ul>
<li><p><strong>enqueue</strong>: Adds an item to the back of the queue, like a new customer joining the end of a ticket line.</p>
</li>
<li><p><strong>dequeue</strong>: Removes and returns the item at the front of the queue.</p>
</li>
<li><p><strong>getFront</strong>: Looks at the item at the front without removing it, like checking who’s first in line.</p>
</li>
<li><p><strong>getRear</strong>: Looks at the item at the back without removing it, like seeing who’s last in line.</p>
</li>
<li><p><strong>isEmpty</strong>: Checks if the queue has no items.</p>
</li>
<li><p><strong>isFull</strong>: Checks if the queue has reached its maximum size.</p>
</li>
<li><p><strong>peek</strong>: Same as <code>getFront</code>, views the front item without removing it, like a quick glance at the first task.</p>
</li>
<li><p><strong>size</strong>: Returns the number of items in the queue, like counting how many people are in line.</p>
</li>
</ul>
<p>Now that you know about queues and their main operations, let's get into the actual implementation and see how it looks in code.</p>
<p>There are a few different ways to implement queues, but in this tutorial, you will learn about <strong>linked list-based queues</strong>, which use a linked list to create the queues.</p>
<p>First, let's briefly learn about the linked list data structure and then move on to the queue implementation.</p>
<h2 id="heading-what-are-linked-lists">What Are Linked Lists?</h2>
<p>A linked list is a method of storing a collection of items where each item, known as a "node," contains two parts: the actual data and a reference (or pointer) to the next item in the list.</p>
<p>Unlike arrays, where all items are stored next to each other in memory, linked lists connect nodes using these references, like a chain.</p>
<p>Linked lists are used to implement queues because they allow efficient <strong>insertion at the end</strong> and <strong>removal from the front</strong>, which are the two main operations of a queue.</p>
<p>In a linked list-based queue, you can add a new node at the tail and remove one from the head in constant time (<code>O(1)</code>) without needing to shift elements, as you would in an array.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741385495/1bfab581-481d-4108-9f48-bf93d9dcf4f1.png" alt="Diagram of a linked list with four nodes connected sequentially. Node 1 is labeled as the head and Node 4 as the tail." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In this tutorial, you are going to use a specific type of linked list called <strong>Circular Doubly Linked List</strong>.</p>
<p>A circular doubly linked list is a type of linked list where each node connects to both the next and previous nodes, and the last node loops back to the first one to form a circle.</p>
<p>This means you can move through the list in both directions and never hit a dead end. This makes it easy to go forward or backward through nodes and helps avoid special cases like handling <code>null</code> at the ends.</p>
<p>In a circular doubly linked list, everything is connected in a loop, which simplifies certain queue operations and keeps things efficient.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741872784/d01a9c89-945e-4b4a-acff-56b7e528ea7e.png" alt="Diagram showing a circular doubly linked list with five nodes labeled from Node 1 (head) to Node 5 (tail), connected in a loop." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You can learn more about circular linked lists in my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-code-linked-lists-with-typescript-handbook/#heading-what-is-a-circular-linked-list">Linked Lists Handbook</a>.</p>
<p>For this tutorial, I’ve already added a circular doubly linked list in <code>src/playground/01-linked-list.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/01-linked-list.ts</span>

<span class="hljs-comment">/**
 * Node for doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> NodeItem&lt;T&gt; {
  value: T;
  next: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  prev: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">value: T</span>) {
    <span class="hljs-built_in">this</span>.value = value;
  }
}

<span class="hljs-comment">/**
 * Circular Doubly Linked List
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> LinkedList&lt;T&gt; {
  <span class="hljs-keyword">private</span> head: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">private</span> tail: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">private</span> currentSize: <span class="hljs-built_in">number</span> = <span class="hljs-number">0</span>;

  <span class="hljs-comment">/**
   * Add a new node to the front of the list
   * @param value The value to add
   */</span>
  prepend(value: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(value);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head = newNode;
    }
    <span class="hljs-built_in">this</span>.currentSize++;
  }

  <span class="hljs-comment">/**
   * Add a new node to the back of the list
   * @param value The value to add
   */</span>
  append(value: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(value);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
    }
    <span class="hljs-built_in">this</span>.currentSize++;
  }

  <span class="hljs-comment">/**
   * Remove and return the value from the front of the list
   * @returns The value at the head or undefined if empty
   */</span>
  deleteHead(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
    }
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">this</span>.head!.value;
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head!.next;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
    }
    <span class="hljs-built_in">this</span>.currentSize--;
    <span class="hljs-keyword">return</span> value;
  }

  <span class="hljs-comment">/**
   * Remove and return the value from the back of the list
   * @returns The value at the tail or undefined if empty
   */</span>
  deleteTail(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
    }
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">this</span>.tail!.value;
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail!.prev;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
    }
    <span class="hljs-built_in">this</span>.currentSize--;
    <span class="hljs-keyword">return</span> value;
  }

  <span class="hljs-comment">/**
   * Get the value at the front without removing it
   * @returns The value at the head or undefined if empty
   */</span>
  getHead(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.head?.value;
  }

  <span class="hljs-comment">/**
   * Get the value at the back without removing it
   * @returns The value at the tail or undefined if empty
   */</span>
  getTail(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.tail?.value;
  }

  <span class="hljs-comment">/**
   * Check if the list is empty
   * @returns True if the list is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/**
   * Get the current size of the list
   * @returns The number of nodes in the list
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.currentSize;
  }
}
</code></pre>
<p>In this module, you have a circular doubly linked list with 8 different methods that will make it easier to build queues later in the tutorial:</p>
<ul>
<li><p><code>prepend</code>: Adds a new value to the <strong>front</strong> of the list.</p>
</li>
<li><p><code>append</code>: Adds a new value to the <strong>end</strong> of the list.</p>
</li>
<li><p><code>deleteHead</code>: Removes and returns the value at the <strong>front</strong>.</p>
</li>
<li><p><code>deleteTail</code>: Removes and returns the value at the <strong>end</strong>.</p>
</li>
<li><p><code>getHead</code>: Returns the front value <strong>without removing it</strong>.</p>
</li>
<li><p><code>getTail</code>: Returns the end value <strong>without removing it</strong>.</p>
</li>
<li><p><code>isEmpty</code>: Checks whether the list has <strong>no items</strong>.</p>
</li>
<li><p><code>size</code>: Returns the <strong>number of items</strong> currently in the list.</p>
</li>
</ul>
<p>Now that your linked list is ready, let's begin creating your first queue!</p>
<h2 id="heading-what-is-a-simple-queue">What is a Simple Queue?</h2>
<p>A Simple Queue follows the basic FIFO rule: you’ll to add items to the back and remove them from the front.</p>
<p>It’s like a line of customers at a ticket counter, where the first person in line buys a ticket first.</p>
<p>To get started, open <code>src/playground/02-simple-queue.ts</code>, where you will find the placeholder for the Simple Queue with its methods:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/02-simple-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Simple Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SimpleQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  ...methods
}
</code></pre>
<p>At the core of this <code>SimpleQueue</code> class, you're using a circular doubly linked list to store the items, and optionally allowing a maximum size limit to control how big the queue can grow.</p>
<ul>
<li><p><code>private list: LinkedList&lt;T&gt;</code> is where the queue's data is stored. Instead of a simple array, you're using a custom linked list, which makes it efficient to add or remove items from either end. The linked list manages the data structure and allows you to focus on how the queue works.</p>
</li>
<li><p><code>private maxSize</code> is an optional limit for how many items the queue can hold. If not provided, the queue can grow as large as needed.</p>
</li>
<li><p>Then, the <code>constructor</code> method that runs when you create a new queue. It creates a new, empty linked list to hold the queue items.</p>
</li>
</ul>
<p>Now, let's implement the queue methods.</p>
<p>Open your code editor and update <code>src/playground/02-simple-queue.ts</code> with the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/02-simple-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Simple Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SimpleQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the queue
   * @param item The element to add
   */</span>
  enqueue(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Queue is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the queue
   * @returns The element at the front or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>As you can see, the linked list greatly simplifies your queue implementation because it acts as the engine behind your queue.</p>
<p>Here's how your Simple Queue works:</p>
<ul>
<li><p><strong>isEmpty()</strong>: This method checks whether the queue contains any items. It calls the <code>isEmpty()</code> method on the linked list, which internally checks if the current size of the list is zero. If the list has no nodes, it returns <code>true</code>, indicating that the queue is empty. This is a basic utility method often used before attempting to dequeue or inspect the queue.</p>
</li>
<li><p><strong>isFull()</strong>: This method determines whether the queue has reached its capacity. It compares the current size of the linked list (via the <code>size()</code> method) to the optional <code>maxSize</code> value. If <code>maxSize</code> is defined and the size is equal to or greater than that limit, it returns <code>true</code>, indicating that no more items can be added. This is useful to prevent overflow in bounded queues.</p>
</li>
<li><p><strong>size()</strong>: This method returns the number of items currently stored in the queue. It directly calls the <code>size()</code> method of the linked list, which tracks how many nodes are present. This allows you to monitor queue usage and remaining capacity.</p>
</li>
<li><p><strong>enqueue()</strong>: This method adds a new item to the end (rear) of the queue. It first checks whether the queue is full by calling the <code>isFull()</code> method. If it is, the method throws an error. Otherwise, it appends the new item to the internal linked list using the <code>append()</code> method, which adds the new node to the tail of the circular doubly linked list.</p>
</li>
<li><p><strong>dequeue()</strong>: This method removes and returns the item at the front of the queue. It calls the <code>deleteHead()</code> method of the linked list, which removes the head node and updates the links of the surrounding nodes to maintain the circular structure. If the queue is empty, it returns <code>undefined</code>.</p>
</li>
<li><p><strong>getFront()</strong>: This method returns the value at the front of the queue without removing it. It uses the <code>getHead()</code> method of the linked list to retrieve the value of the head node. This operation does not modify the queue and is useful for previewing the next item to be dequeued.</p>
</li>
<li><p><strong>getRear()</strong>: This method returns the value at the rear of the queue without removing it. It uses the <code>getTail()</code> method of the linked list, which returns the value of the tail node. This helps you inspect the most recently added item without altering the queue.</p>
</li>
<li><p><strong>peek()</strong>: This method is an alias for <code>getFront()</code>. It returns the item at the front of the queue without removing it. Internally, it calls <code>getFront()</code> to get the head value. This is often used in queue APIs to check the next item in line.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749742108067/3f5aab62-8314-4889-925a-cb9d52d9a277.png" alt="Flowchart illustrating queue operations. The process starts with either an enqueue or dequeue operation. Enqueue checks if the queue is full: if yes, triggers an error; if no, it adds an element, updates the rear pointer, and ends. Dequeue checks if the queue is empty: if yes, triggers an error; if no, removes an element, updates the front pointer, and ends." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You’ve just implemented your first queue in TypeScript. To make sure that your implementation works correctly, run the following command in your terminal at the root of the project:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 02
</code></pre>
<p>If any of the tests fail, use the final example from <code>src/examples/02-simple-queue.ts</code> to debug the issue, and then run the tests again.</p>
<p>If all tests pass, you can proceed to the next section, where you'll implement a Circular Queue.</p>
<h2 id="heading-what-is-a-circular-queue">What is a Circular Queue?</h2>
<p>A <code>CircularQueue</code> is a fixed-size queue where the last position connects back to the first. This allows you to reuse space after removing items.</p>
<p>Imagine a buffet line with a limited number of plates: when someone takes a plate from the front, a new one is added at the back, using the same space again.</p>
<p>The <code>CircularQueue</code> is quite similar to the <code>SimpleQueue</code>, but it has a few unique differences.</p>
<p>Let’s modify <code>src/playground/03-circular-queue.ts</code> and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/03-circular-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Circular Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Required maximum size of the circular queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the queue
   * @param item The element to add
   */</span>
  enqueue(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Circular queue is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the queue
   * @returns The element at the front or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>This may look very similar to a <code>SimpleQueue</code>, but there are a few key differences:</p>
<ul>
<li><p><strong>Constructor Difference</strong>: Unlike the <code>SimpleQueue</code>, the <code>CircularQueue</code> <strong>requires</strong> a <code>maxSize</code> parameter during instantiation. This enforces a strict upper limit on how many elements can be in the queue at once.</p>
<p>  In contrast, <code>SimpleQueue</code> treats <code>maxSize</code> as optional and allows unbounded queues. By making the size mandatory, <code>CircularQueue</code> is better suited for fixed-size buffer scenarios where memory or resource control is important (for example, in real-time systems or caching).</p>
</li>
<li><p><strong>enqueue()</strong>: This method is almost identical to the one in <code>SimpleQueue</code>, but the key difference lies in the design intent. In <code>CircularQueue</code>, throwing an error when the queue is full is part of the contract and it assumes that you’re managing a fixed buffer.</p>
<p>  The circular nature comes into play conceptually: once full, no more data can enter unless older entries are removed, which mimics a circular overwrite mechanism (though this specific implementation doesn’t auto-overwrite).</p>
</li>
<li><p><strong>isFull()</strong>: This method behaves the same as in <code>SimpleQueue</code> when a <code>maxSize</code> is set, but in <code>CircularQueue</code>, it’s always applicable because <code>maxSize</code> is required. The consistent presence of a size limit makes the queue predictable and ideal for bounded use cases like streaming data and rate-limited processing.</p>
</li>
</ul>
<p>Now, let's test the implementation to see if it works:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 03
</code></pre>
<p>If any of the tests fail, use the final <code>/examples</code> directory to debug the issue.</p>
<p>If the tests pass, you'll be ready to move on to the next section, where you will learn about double-ended queues.</p>
<h2 id="heading-what-is-a-double-ended-queue">What is a Double Ended Queue?</h2>
<p>A double-ended queue (deque) lets you add or remove items from both the front and the back.</p>
<p>It’s like a line at a bus stop where people can join or leave from either end.</p>
<p>Let’s modify <code>src/playground/04-double-ended-queue.ts</code> and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/04-double-ended-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Double-Ended Queue (Deque) implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Deque&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the deque
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the front of the deque
   * @param item The element to add
   */</span>
  enqueueFront(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Deque is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.prepend(item);
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the deque
   * @param item The element to add
   */</span>
  enqueueRear(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Deque is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the deque
   * @returns The element at the front or undefined if empty
   */</span>
  dequeueFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the rear of the deque
   * @returns The element at the rear or undefined if empty
   */</span>
  dequeueRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteTail();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the deque is empty
   * @returns True if the deque is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the deque is full
   * @returns True if the deque is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the deque
   * @returns The number of elements in the deque
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>Now, let's go through the methods:</p>
<ul>
<li><p><strong>enqueueFront()</strong>: This method allows adding an element to the <strong>front</strong> of the deque, unlike in <code>SimpleQueue</code> or <code>CircularQueue</code> which only support adding to the rear. Internally, it uses <code>list.prepend(item)</code> to insert the item at the head.</p>
<p>  This operation makes the deque suitable for use cases where elements need to be pushed and popped from both ends, like in undo/redo systems or task schedulers.</p>
</li>
<li><p><strong>enqueueRear()</strong>: This behaves similarly to <code>SimpleQueue</code>’s <code>enqueue</code>, adding elements to the <strong>rear</strong> using <code>list.append(item)</code>.</p>
<p>  The distinction in <code>Deque</code> is that this is just one of two symmetric operations and it gives you full double-ended control.</p>
</li>
<li><p><strong>dequeueFront()</strong>: This removes and returns the element from the <strong>front</strong> of the deque using <code>list.deleteHead()</code>.</p>
<p>  While similar to the <code>dequeue</code> method in queues, the naming here is explicit to clarify that it's operating on the front and can be paired with a rear counterpart.</p>
</li>
<li><p><strong>dequeueRear()</strong>: This is a unique feature to deques, it removes and returns the element at the <strong>rear</strong> using <code>list.deleteTail()</code>. This complements <code>dequeueFront()</code> and enables LIFO (stack-like) behavior if needed.</p>
</li>
<li><p><strong>Constructor Difference</strong>: Like <code>SimpleQueue</code>, the <code>Deque</code> accepts an optional <code>maxSize</code>. This allows for flexible configurations.</p>
<p>  You can have unbounded deques when <code>maxSize</code> is not provided, or fixed-size deques when constraints are important. This is in contrast to <code>CircularQueue</code>, which requires a max size.</p>
</li>
</ul>
<p>Once you have completed the implementation, run the following command to test the module:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 04
</code></pre>
<p>Now, you're ready to move on to the last section of the tutorial, where you'll learn about the Priority Queue.</p>
<h2 id="heading-what-is-a-priority-queue">What is a Priority Queue?</h2>
<p>A priority queue processes items based on their priority, not their order of arrival.</p>
<p>Higher-priority items are removed first, like an emergency room where patients with severe conditions are treated before others.</p>
<p>Let’s modify <code>src/playground/05-priority-queue.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/05-priority-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList, NodeItem } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Interface for an element with priority
 */</span>
<span class="hljs-keyword">interface</span> PriorityItem&lt;T&gt; {
  value: T;
  priority: <span class="hljs-built_in">number</span>;
}

<span class="hljs-comment">/**
 * Priority Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> PriorityQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;PriorityItem&lt;T&gt;&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the priority queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;PriorityItem&lt;T&gt;&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the queue based on its priority
   * Higher priority numbers are dequeued first
   * @param value The value to add
   * @param priority The priority of the value (higher number = higher priority)
   */</span>
  enqueue(value: T, priority: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Priority queue is full"</span>);
    }

    <span class="hljs-keyword">const</span> newItem: PriorityItem&lt;T&gt; = { value, priority };
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.list.prepend(newItem);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>];
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">while</span> (
      current &amp;&amp;
      current.value.priority &gt;= priority &amp;&amp;
      count &lt; <span class="hljs-built_in">this</span>.size()
    ) {
      current = current.next;
      count++;
    }

    <span class="hljs-keyword">if</span> (count === <span class="hljs-built_in">this</span>.size()) {
      <span class="hljs-built_in">this</span>.list.append(newItem);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(newItem);
      newNode.next = current;
      newNode.prev = current!.prev;
      <span class="hljs-keyword">if</span> (current!.prev) {
        current!.prev.next = newNode;
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>] = newNode;
      }
      current!.prev = newNode;
      <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>]) {
        <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>] = newNode;
      }
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"tail"</span>]!.next = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>];
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>]!.prev = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"tail"</span>];
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"currentSize"</span>]++;
    }
  }

  <span class="hljs-comment">/**
   * Remove and return the element with the highest priority from the queue
   * @returns The value with the highest priority or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead()?.value;
  }

  <span class="hljs-comment">/**
   * Get the element with the highest priority without removing it
   * @returns The value at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead()?.value;
  }

  <span class="hljs-comment">/**
   * Get the element with the lowest priority without removing it
   * @returns The value at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail()?.value;
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the element with the highest priority without removing it
   * @returns The value at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>Let's understand how the methods work within a Priority Queue:</p>
<ul>
<li><p><strong>enqueue()</strong>: This method inserts a new element into the queue based on its <code>priority</code>. Unlike other queue types where order is based on insertion time, <code>PriorityQueue</code> uses a sorting mechanism where elements with higher <code>priority</code> values are placed closer to the front.</p>
<p>  The method traverses the linked list from the head, searching for the correct position where the new item should be inserted so that the list remains sorted in descending priority order.</p>
<p>  It manually adjusts the <code>prev</code> and <code>next</code> pointers to keep the circular doubly linked list intact. This sorting during insertion ensures quick access to the highest priority element later.</p>
</li>
<li><p><strong>dequeue()</strong>: This method removes and returns the element with the highest priority, which is always positioned at the front of the list.</p>
<p>  Internally, it calls <code>deleteHead()</code> and then returns the <code>value</code> from the <code>PriorityItem&lt;T&gt;</code> node. Because items are sorted during insertion, this operation is always efficient and retrieves the correct item.</p>
</li>
<li><p><strong>getFront()</strong>: This retrieves the value at the front of the queue without removing it. Since the list is sorted in descending priority, this value always represents the highest priority item.</p>
</li>
<li><p><strong>getRear()</strong>: This returns the value at the rear of the queue, which is the item with the <strong>lowest</strong> priority. It accesses the last element in the list using <code>getTail()</code> and extracts the <code>value</code>.</p>
</li>
<li><p><strong>isEmpty()</strong>: This checks whether the queue contains any elements by delegating to the linked list’s <code>isEmpty()</code> method.</p>
</li>
<li><p><strong>isFull()</strong>: This checks whether the queue has reached its maximum allowed size. It compares the current size with <code>maxSize</code> if it's defined.</p>
</li>
<li><p><strong>peek()</strong>: This is functionally equivalent to <code>getFront()</code>. It provides a clearer semantic name when users want to examine the highest-priority element without removing it.</p>
</li>
<li><p><strong>size()</strong>: This returns the total number of items currently in the priority queue. It's useful for monitoring capacity or debugging.</p>
</li>
<li><p><strong>Key Differences</strong>: The priority queue differs from other queue types by enforcing order during insertion based on a numeric priority.</p>
<p>  This enables <strong>constant-time access to the highest priority element</strong> but introduces <strong>linear-time insertion</strong> complexity due to the need to find the correct place for each new element.</p>
<p>  It supports advanced scheduling and load balancing use cases where task urgency or importance matters more than arrival time.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749743948626/78505f93-d7fd-4c63-b59a-5db1edcdae6c.png" alt="Flowchart illustrating the process of inserting an element into a priority queue. It begins by checking if the queue is empty, then assesses priority, updates the queue, traverses it if necessary, and continually checks for the correct position to insert." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Once you’re done with the implementation, run the following command to test your code:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 05
</code></pre>
<p>That’s it, congratulations!</p>
<p>You have successfully completed the tutorial and learned about queues and their different variations. Great job!</p>
<p>Before reaching conclusions, let’s briefly learn about where to use queues and where to avoid them. We’ll also discuss the bottlenecks and issues that queues may create if not used correctly and in the right place.</p>
<h2 id="heading-when-to-use-queues-and-when-to-avoid-them"><strong>When to Use Queues (and When to Avoid Them)</strong></h2>
<p>Queues are ideal in scenarios where tasks or data must be processed in the exact order they arrive, such as in job scheduling and event handling systems.</p>
<p>For example, when multiple print jobs are sent to a printer, a queue can make sure each document is printed in the order it was submitted.</p>
<p>Similarly, queues are used in operating systems for managing tasks in thread pools or CPU scheduling (for example, Round Robin), where order is crucial.</p>
<p>Queues are also heavily used in asynchronous communication systems such as message brokers like RabbitMQ and Kafka.</p>
<p>In these systems, producers and consumers operate independently: a producer pushes messages into the queue, and a consumer processes them later.</p>
<p>This pattern is extremely useful in microservices architecture or serverless environments, where different parts of a system need to remain loosely coupled and highly scalable.</p>
<p>Similarly, in real-time systems like video streaming or sensor data ingestion, queues help buffer incoming data to avoid data loss and allow for smooth downstream processing.</p>
<h3 id="heading-when-to-avoid-queues">When to Avoid Queues</h3>
<p>Queues are not well-suited for problems that require random access to elements, complex search operations, or sorting.</p>
<p>Since queues typically allow insertion at one end and removal from the other, they’re inefficient for use cases where you frequently need to access elements in the middle or search through all items.</p>
<p>An array, tree, or hash map would serve better in such cases.</p>
<p>Using queues inappropriately can introduce unnecessary complexity and hidden bottlenecks.</p>
<p>For instance, blindly placing a queue between every microservice might decouple components but also make debugging and failure handling more difficult.</p>
<p>Over-queuing can also lead to backpressure problems where queues grow uncontrollably under high load which will increase latency or even crashing the system if not managed properly.</p>
<p>So you should use queues deliberately: when order, buffering, or async processing is required.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Queues are a basic data structure that work well when you need order and async processing.</p>
<p>Queues are useful for handling tasks, streaming data, or coordinating services, and making sure things run smoothly and efficiently.</p>
<p>But they aren't suitable for every problem. It's important to understand their pros and cons to use them correctly and avoid unnecessary complexity.</p>
<p>Thanks for following along with this tutorial. You can follow me on <a target="_blank" href="https://x.com/Yazdun">X</a>, where I share more useful tips on data structures and web development.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Code Linked Lists with TypeScript: A Handbook for Developers ]]>
                </title>
                <description>
                    <![CDATA[ A linked list is a data structure where each item, called a node, contains data and a pointer to the next node. Unlike arrays, which store elements in contiguous memory, linked lists connect nodes that can be scattered across memory. In this hands-on... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-code-linked-lists-with-typescript-handbook/</link>
                <guid isPermaLink="false">683dea64b88211830493d3aa</guid>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ singlylinkedlist ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #linkedlists ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #DoublyLinkedList ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yazdun ]]>
                </dc:creator>
                <pubDate>Mon, 02 Jun 2025 18:16:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748874008549/f7890467-2c7d-4558-a3ca-6094400530bc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A linked list is a data structure where each item, called a node, contains data and a pointer to the next node.</p>
<p>Unlike arrays, which store elements in contiguous memory, linked lists connect nodes that can be scattered across memory.</p>
<p>In this hands-on tutorial, you’ll build linked lists from scratch in TypeScript, starting with a basic singly linked list and progressing to advanced variations like doubly linked lists and circular lists.</p>
<h2 id="heading-heres-what-well-cover">Here’s What We’ll Cover</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-getting-started">Getting Started</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-linked-lists">What are Linked Lists?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-singly-linked-list">What is a Singly Linked List?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-generic-node-structure-for-a-singly-linked-list">How to Create a Generic Node Structure for a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-a-singly-linked-list">How to Implement a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-head-pointer-in-a-linked-list">What is the head Pointer in a Linked List?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepend-a-node-in-a-singly-linked-list">How to Prepend a Node in a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-append-a-node-in-a-singly-linked-list">How to Append a Node in a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-head-of-a-singly-linked-list">How to Delete the head of a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-last-node-of-a-singly-linked-list">How to Delete the Last Node of a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-a-node-from-a-singly-linked-list">How to Delete a Node from a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-find-a-node-in-a-singly-linked-list">How to Find a Node in a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-insert-a-node-at-a-specific-position-in-a-singly-linked-list">How to Insert a Node at a Specific Position in a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-traverse-a-singly-linked-list">How to Traverse a Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-your-singly-linked-list">How to Test Your Singly Linked List</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-doubly-linked-list">What is a Doubly Linked List?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-generic-node-structure-for-a-doubly-linked-list">How to Create a Generic Node Structure for a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-a-doubly-linked-list">How to Implement a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepend-a-node-in-a-doubly-linked-list">How to Prepend a Node in a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-append-a-node-in-a-doubly-linked-list">How to Append a Node in a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-head-of-a-doubly-linked-list">How to Delete the Head of a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-last-node-of-a-doubly-linked-list">How to Delete the Last Node of a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-a-node-from-a-doubly-linked-list">How to Delete a Node from a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-find-a-node-in-a-doubly-linked-list">How to Find a Node in a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-traverse-a-doubly-linked-list">How to Traverse a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-insert-a-node-at-a-specific-position-in-a-doubly-linked-list">How to Insert a Node at a Specific Position in a Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-your-doubly-linked-list">How to Test Your Doubly Linked List</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circular-linked-list">What is a Circular Linked List?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circular-singly-linked-list">What is a Circular Singly Linked List?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-generic-node-structure-for-a-circular-singly-linked-list">How to Create a Generic Node Structure for a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-a-circular-singly-linked-list">How to Implement a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepend-a-node-in-a-circular-singly-linked-list">How to Prepend a Node in a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-append-a-node-in-a-circular-singly-linked-list">How to Append a Node in a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-head-of-a-circular-singly-linked-list">How to Delete the Head of a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-last-node-of-a-circular-singly-linked-list">How to Delete the Last Node of a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-a-node-from-a-circular-singly-linked-list">How to Delete a Node from a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-find-a-node-in-a-circular-singly-linked-list">How to Find a Node in a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-traverse-a-circular-singly-linked-list">How to Traverse a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-insert-a-node-at-a-specific-position-in-a-circular-singly-linked-list">How to Insert a Node at a Specific Position in a Circular Singly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-your-circular-singly-linked-list">How to Test Your Circular Singly Linked List</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circular-doubly-linked-list">What is a Circular Doubly Linked List?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-generic-node-structure-for-a-circular-doubly-linked-list">How to Create a Generic Node Structure for a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-a-circular-doubly-linked-list">How to Implement a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepend-a-node-in-a-circular-doubly-linked-list">How to Prepend a Node in a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-append-a-node-in-a-circular-doubly-linked-list">How to Append a Node in a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-last-node-of-a-circular-doubly-linked-list">How to Delete the Last Node of a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-the-head-of-a-circular-doubly-linked-list">How to Delete the Head of a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-find-a-node-in-a-circular-doubly-linked-list">How to Find a Node in a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-traverse-a-circular-doubly-linked-list">How to Traverse a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-delete-a-node-from-a-circular-doubly-linked-list">How to Delete a Node from a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-insert-a-node-at-a-specific-position-in-a-circular-doubly-linked-list">How to Insert a Node at a Specific Position in a Circular Doubly Linked List</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-your-circular-doubly-linked-list">How to Test Your Circular Doubly Linked List</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-linked-lists-and-when-to-avoid-them">When to Use Linked Lists (and When to Avoid Them)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-use-linked-lists">Why Use Linked Lists?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-use-cases">Real-World Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-not-to-use-linked-lists">When Not to Use Linked Lists</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-better-alternatives-for-specific-cases">Better Alternatives for Specific Cases</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li><p><strong>TypeScript:</strong> You need to know <a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/">TypeScript basics</a>, such as interfaces, types, and classes.</p>
</li>
<li><p><strong>Algorithm fundamentals:</strong> You need a basic understanding of data structures and algorithms. For example, you should be comfortable analyzing time and space complexity using <a target="_blank" href="https://www.freecodecamp.org/news/big-o-cheat-sheet-time-complexity-chart/">Big-O notation</a>.</p>
</li>
</ol>
<h2 id="heading-getting-started"><strong>Getting Started</strong></h2>
<p>To get started with this tutorial, you’ll use a playground project designed to help you implement linked lists and follow each step hands-on.</p>
<p>Clone the project from the <a target="_blank" href="https://github.com/Yazdun/fcc-linked-list">GitHub repository</a> and code along with the tutorial.</p>
<p>The project structure is as follows:</p>
<pre><code class="lang-plaintext">fcc-linked-list/
├── src/
│   ├── examples/
│   │   ├── circular-1.ts
│   │   ├── circular-2.ts
│   │   ├── doubly.ts
│   │   └── singly.ts
│   └── playground/
│       ├── circular-1.ts
│       ├── circular-2.ts
│       ├── doubly.ts
│       └── singly.ts
</code></pre>
<p>The <code>examples</code> directory contains the final version of each implementation. If you get stuck, you can look at these solutions as a last resort!</p>
<h2 id="heading-what-are-linked-lists">What are Linked Lists?</h2>
<p>A linked list is a collection of elements called nodes, where each node contains data and a pointer to the next node, with the last node’s pointer typically pointing to <code>null</code> to mark the end of the list.</p>
<p>Some linked lists have extra pointers to speed up changes anywhere in the list. But finding a node can be slow because you have to follow each pointer one by one and can't jump directly to a node.</p>
<p>Linked lists are the foundation for data structures like queues and stacks. The linked lists you create in this tutorial will support many other data structures.</p>
<p>While linked lists can perform many operations, this tutorial will focus on the following:</p>
<ul>
<li><p><strong>prepend:</strong> adds a node to the beginning of the list.</p>
</li>
<li><p><strong>append:</strong> adds a node to the end of the list.</p>
</li>
<li><p><strong>delete:</strong> removes a specific node from the list.</p>
</li>
<li><p><strong>deleteTail:</strong> removes the last node in the list.</p>
</li>
<li><p><strong>deleteHead:</strong> removes the first node in the list.</p>
</li>
<li><p><strong>insertAt:</strong> inserts a node at a specific position.</p>
</li>
<li><p><strong>find:</strong> searches for and returns a node in the list.</p>
</li>
<li><p><strong>traverse:</strong> visits each node in the list, usually from head to tail, for reading or processing data.</p>
</li>
</ul>
<p>Once you understand these basic operations, you'll be able to implement any operation on your linked lists.</p>
<p>Now that you understand the concept, let's move to the next section and create your first linked list.</p>
<h2 id="heading-what-is-a-singly-linked-list"><strong>What is a Singly Linked List?</strong></h2>
<p>In this first section, you'll create the simplest type of linked list, called a Singly Linked List.</p>
<p>It's called "Singly Linked" because each node points to only one other node, which is the next one in the list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748530545447/8dbffb8d-c941-4c57-934b-22c0335bdd6b.png" alt="Diagram of a singly linked list with four nodes labeled A, B, C, and D. It starts with the head at Node A and ends with the tail at Node D, pointing to NULL. Each node points to the next node in sequence." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-create-a-generic-node-structure-for-a-singly-linked-list">How to Create a Generic Node Structure for a Singly Linked List</h3>
<p>To start building a singly linked list, you need a <code>Node</code> structure that holds two main parts:</p>
<ul>
<li><p><strong>data</strong>: Stores the node’s value.</p>
</li>
<li><p><strong>Next pointer</strong>: Links to the next node in the list or <code>null</code> if there’s no next node.</p>
</li>
</ul>
<p>Open <code>src/playground/singly.ts</code>, where you'll find a class named <code>N</code>. Change it to the following code to set up the node structure:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

<span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node value */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given value */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">value: T</span>) {
    <span class="hljs-built_in">this</span>.data = value;
  }
}
</code></pre>
<p>Here’s how the node structure works:</p>
<ol>
<li><p>Builds a <a target="_blank" href="https://www.typescriptlang.org/fr/docs/handbook/2/generics.html">generic</a> <code>Node</code>: Uses <code>&lt;T&gt;</code> to handle any data type.</p>
</li>
<li><p>Stores the node’s value: Assigns the value to the <code>data</code> property.</p>
</li>
<li><p>Link to the next node: Sets the <code>next</code> pointer to the next node or <code>null</code> if there isn't one.</p>
</li>
<li><p>Initializes the node: Takes a value in the constructor and assigns it to <code>data</code>.</p>
</li>
</ol>
<p>Now, you can use the <code>N</code> class to create nodes in your singly linked list.</p>
<h3 id="heading-how-to-implement-a-singly-linked-list">How to Implement a Singly Linked List</h3>
<p>Let's use the Node class you just created to build your singly linked list.</p>
<p>Open <code>src/playground/singly.ts</code> where you'll find the <code>SinglyLinkedList</code> class with a <code>head</code> pointer and several methods:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

<span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node value */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given value */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">value: T</span>) {
    <span class="hljs-built_in">this</span>.data = value;
  }
}

<span class="hljs-comment">/** Singly linked list implementation */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SinglyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(val: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes head node */</span>
  deleteHead(): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes tail node */</span>
  deleteTail(): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes first node with given value */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Finds node with given value */</span>
  find(data: T): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Logs all node values */</span>
  traverse(): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Inserts node at given position */</span>
  insertAt(pos: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">void</span> {}
}
</code></pre>
<p>By the end of this section, you'll create each of these methods. But first, let's discuss the <code>head</code> pointer.</p>
<h3 id="heading-what-is-the-head-pointer-in-a-linked-list">What is the <code>head</code> Pointer in a Linked List?</h3>
<p>The <code>head</code> is the first node in the list, and you begin from <code>head</code> when going through the list.</p>
<p>You follow each node's <code>next</code> pointer until you get to the last node, where next is <code>null</code>.</p>
<p>If <code>head</code> is <code>null</code>, the list is empty.</p>
<p>A non-empty singly linked list needs a head to be valid, or it’s broken.</p>
<p>With this knowledge, you're ready to start working on the operations.</p>
<h3 id="heading-how-to-prepend-a-node-in-a-singly-linked-list">How to Prepend a Node in a Singly Linked List</h3>
<p>The goal is to add a new node to the beginning of your singly linked list and update the <code>head</code> pointer to this new node.</p>
<p>Modify the <code>prepend</code> method in your <code>SinglyLinkedList</code> class in <code>src/playground/singly.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

prepend(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);
  newNode.next = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-built_in">this</span>.head = newNode;
}
</code></pre>
<p>The <code>data</code> prop holds the value for the new node. Here’s how <code>prepend</code> works:</p>
<ul>
<li><p>Creates a new node with the given <code>data</code>.</p>
</li>
<li><p>Points the new node’s <code>next</code> to the current <code>head</code>.</p>
</li>
<li><p>Sets the <code>head</code> to the new node.</p>
</li>
</ul>
<p>Now, the <code>head</code> points to the new node, and the previous <code>head</code> is the second node in the list.</p>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-append-a-node-in-a-singly-linked-list">How to Append a Node in a Singly Linked List</h3>
<p>The goal is to add a new node to the end of your singly linked list.</p>
<p>Change the <code>append</code> method in your <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// src/playground/singly.ts</span>

append(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">while</span> (current.next) {
    current = current.next;
  }

  current.next = newNode;
}
</code></pre>
<p>To add a new node to the end of the list, you first need to find the last node. In a non-empty singly linked list, the last node's <code>next</code> pointer always points to <code>null</code>.</p>
<p>In other words, to find the last node in a non-empty singly linked list, look for the node whose <code>next</code> pointer is <code>null</code>.</p>
<p>To append a new node, you should follow these steps:</p>
<ul>
<li><p>Create a new node with the given value.</p>
</li>
<li><p>Check if the <code>head</code> is <code>null</code>. If it is, the list is empty, so set the <code>head</code> to the new node.</p>
</li>
<li><p>If the list has nodes, find the last node by looping through the list.</p>
</li>
<li><p>Start with a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>Keep moving <code>current</code> to the <code>next</code> node until you hit a node with no <code>next</code> node (where <code>next</code> is <code>null</code>).</p>
</li>
<li><p>Link the last node’s next to the new node.</p>
</li>
</ul>
<p>Now, the new node is the last node, and its <code>next</code> points to <code>null</code>.</p>
<p>This runs in O(n) time because you may need to traverse the entire list to find the last node.</p>
<h3 id="heading-how-to-delete-the-head-of-a-singly-linked-list">How to Delete the <code>head</code> of a Singly Linked List</h3>
<p>The goal is to delete the <code>head</code> of the list. Go ahead and update the <code>deleteHead</code> method in your <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

deleteHead(): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head.next;
  }
}
</code></pre>
<p>You just need to move the <code>head</code> pointer to the second node in the list. The second node is <code>head.next</code>, so all you have to do is set <code>head</code> to <code>head.next</code>.</p>
<p>And just like that, the old <code>head</code> is deleted!</p>
<h3 id="heading-how-to-delete-the-last-node-of-a-singly-linked-list">How to Delete the Last Node of a Singly Linked List</h3>
<p>The goal is to delete the last node, called the <code>tail</code>, from your singly linked list.</p>
<p>The <code>tail</code> is the node whose <code>next</code> pointer is <code>null</code>.</p>
<p>Modify the <code>deleteTail</code> method in your <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

deleteTail(): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head.next) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">while</span> (current.next &amp;&amp; current.next.next) {
    current = current.next;
  }
  current.next = <span class="hljs-literal">null</span>;
}
</code></pre>
<p>Here’s how <code>deleteTail</code> works:</p>
<ol>
<li><p>If the list is empty, it stops the operation because there is no <code>tail</code> to remove.</p>
</li>
<li><p>If the head's <code>next</code> is <code>null</code>, the list has only one node, which serves as both the <code>head</code> and the <code>tail</code>. To empty the list, simply set the <code>head</code> to <code>null</code>.</p>
</li>
<li><p>If the list has more than one node, it finds the node right before the <code>tail</code>. It starts with a pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> forward until its <code>next</code> node is the <code>tail</code>. Then, it sets the <code>next</code> pointer of this node to <code>null</code> to make it the <code>tail</code>.</p>
</li>
<li><p>Now, the last node is removed, and the new <code>tail</code>’s <code>next</code> points to <code>null</code>.</p>
</li>
</ol>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node before the <code>tail</code>.</p>
<h3 id="heading-how-to-delete-a-node-from-a-singly-linked-list">How to Delete a Node from a Singly Linked List</h3>
<p>The goal is to remove the first occurrence of a node with a given value from your singly linked list.</p>
<p>Let's start by changing the <code>delete</code> method in your <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

<span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.data === data) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head.next;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">while</span> (current.next) {
    <span class="hljs-keyword">if</span> (current.next.data === data) {
      current.next = current.next.next;
      <span class="hljs-keyword">return</span>;
    }
    current = current.next;
  }
}
</code></pre>
<p>Here’s how <code>delete</code> works:</p>
<ul>
<li><p>The <code>data</code> prop is the value to find and remove</p>
</li>
<li><p>If the list is empty, it stops the operation because there is nothing to delete.</p>
</li>
<li><p>It checks if the <code>head</code> node’s value matches <code>data</code> prop. If it does, you don’t need to search further because the <code>head</code> is the node to delete, so it moves the <code>head</code> to <code>head.next</code> to remove the old <code>head</code>.</p>
</li>
<li><p>If the <code>head</code> doesn't match, it creates a new pointer called <code>current</code> starting at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list as long as there is a next node, and checks if the next node's value matches the <code>data</code> prop.</p>
</li>
<li><p>If a match is found, it removes the <code>next</code> node by connecting <code>current</code>’s <code>next</code> to the node after it.</p>
</li>
<li><p>This takes the matched node out of the list because <code>current</code> now points to the node after the one you want to remove.</p>
</li>
<li><p>If no match is found, it keeps moving <code>current</code> to the next node until the end.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node.</p>
<h3 id="heading-how-to-find-a-node-in-a-singly-linked-list">How to Find a Node in a Singly Linked List</h3>
<p>The goal is to find the first occurrence of a node with the given value.</p>
<p>Modify the <code>find</code> method inside the <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

find(data: T): N&lt;T&gt; | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">while</span> (current) {
    <span class="hljs-keyword">if</span> (current.data === data) <span class="hljs-keyword">return</span> current;
    current = current.next;
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>The <code>data</code> prop is the value you're searching for.</p>
<p>Here's how <code>find</code> works:</p>
<ul>
<li><p>If the <code>head</code> is <code>null</code>, it returns <code>null</code> because the list is empty and there are no nodes to find.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list while it exists and checks if its value matches <code>data</code>.</p>
</li>
<li><p>If a match is found, it returns the <code>current</code> node because it holds the value you’re looking for.</p>
</li>
<li><p>If no match is found, it moves <code>current</code> to the <code>next</code> node and keeps checking until the end.</p>
</li>
<li><p>If you reach the end without a match, it returns <code>null</code>.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node.</p>
<h3 id="heading-how-to-insert-a-node-at-a-specific-position-in-a-singly-linked-list">How to Insert a Node at a Specific Position in a Singly Linked List</h3>
<p>The goal is to add a new node at a specific position in your singly linked list.</p>
<p>Modify the <code>insertAt</code> method in your <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

insertAt(pos: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);
  <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">if</span> (pos &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"failed"</span>);

  <span class="hljs-keyword">if</span> (pos === <span class="hljs-number">0</span>) {
    newNode.next = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">let</span> idx = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">while</span> (current &amp;&amp; idx &lt; pos - <span class="hljs-number">1</span>) {
    current = current.next;
    idx++;
  }

  <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"failed"</span>);

  newNode.next = current.next;
  current.next = newNode;
}
</code></pre>
<p>The <code>pos</code> prop is the position in the list, and <code>data</code> is the value.</p>
<p>Here’s how <code>insertAt</code> works:</p>
<ul>
<li><p>It creates a new node with the given value.</p>
</li>
<li><p>If the <code>pos</code> is negative, it stops the operation with an error because it's not valid.</p>
</li>
<li><p>If <code>pos</code> is 0, it inserts the node at the head. It links the new node's <code>next</code> to the current <code>head</code>, makes the new node the head, and stops the operation.</p>
</li>
<li><p>If the position is not 0, then it creates a pointer called <code>current</code> at the head and a counter called <code>idx</code> at 0.</p>
</li>
<li><p>It moves <code>current</code> through the list until you reach the node just before the desired position, increasing <code>idx</code> as you go.</p>
</li>
<li><p>If you reach the end of the list or the position is too large, it stops with an error.</p>
</li>
<li><p>It links the new node's <code>next</code> to the node that is currently after the <code>current</code> node.</p>
</li>
<li><p>It links <code>current</code>’s <code>next</code> to the new node to insert it in the list.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the list to find the insertion point.</p>
<h3 id="heading-how-to-traverse-a-singly-linked-list">How to Traverse a Singly Linked List</h3>
<p>The goal is to log the values of all nodes in your singly linked list.</p>
<p>Modify the <code>traverse</code> method inside the <code>SinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

traverse(): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">while</span> (current) {
    <span class="hljs-built_in">console</span>.log(current.data);
    current = current.next;
  }
}
</code></pre>
<p>Here's how <code>traverse</code> works:</p>
<ul>
<li><p>It starts by setting the <code>current</code> pointer to <code>head</code> to begin at the start of the list. If <code>head</code> is <code>null</code>, the list is empty.</p>
</li>
<li><p>If there are nodes in the list, it uses a <code>while (current)</code> loop to visit each one. In each loop, it logs <code>current.data</code> to display the node's value, then moves the <code>current</code> pointer to <code>current.next</code> to go to the next node.</p>
</li>
<li><p>This loop continues until <code>current</code> becomes <code>null</code>, meaning you've reached the end of the list.</p>
</li>
</ul>
<p>Overall, the time complexity is O(n) due to traversing the whole list.</p>
<h3 id="heading-how-to-test-your-singly-linked-list">How to Test Your Singly Linked List</h3>
<p>Congratulations! You've successfully created your singly linked list.</p>
<p>Here's what the final code should look like:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/singly.ts</span>

<span class="hljs-comment">/** Node for singly linked list */</span>
<span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node value */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given value */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">value: T</span>) {
    <span class="hljs-built_in">this</span>.data = value;
  }
}

<span class="hljs-comment">/** Singly linked list implementation */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SinglyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);
    newNode.next = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-built_in">this</span>.head = newNode;
  }

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (current.next) {
      current = current.next;
    }

    current.next = newNode;
  }

  <span class="hljs-comment">/** Removes head node */</span>
  deleteHead(): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head.next;
    }
  }

  <span class="hljs-comment">/** Removes tail node */</span>
  deleteTail(): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head.next) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">while</span> (current.next &amp;&amp; current.next.next) {
      current = current.next;
    }

    current.next = <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Removes first node with given value */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.data === data) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head.next;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (current.next) {
      <span class="hljs-keyword">if</span> (current.next.data === data) {
        current.next = current.next.next;
        <span class="hljs-keyword">return</span>;
      }

      current = current.next;
    }
  }

  <span class="hljs-comment">/** Finds node with given value */</span>
  find(data: T): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (current) {
      <span class="hljs-keyword">if</span> (current.data === data) <span class="hljs-keyword">return</span> current;
      current = current.next;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Logs all node values */</span>
  traverse(): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">while</span> (current) {
      <span class="hljs-built_in">console</span>.log(current.data);
      current = current.next;
    }
  }

  <span class="hljs-comment">/** Inserts node at given position */</span>
  insertAt(pos: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> N(data);
    <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">if</span> (pos &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"failed"</span>);

    <span class="hljs-keyword">if</span> (pos === <span class="hljs-number">0</span>) {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> idx = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">while</span> (current &amp;&amp; idx &lt; pos - <span class="hljs-number">1</span>) {
      current = current.next;
      idx++;
    }

    <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"failed"</span>);

    newNode.next = current.next;
    current.next = newNode;
  }
}
</code></pre>
<p>After you finish the implementation, run the following command to test your singly linked list:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file singly
</code></pre>
<p>If any tests fail, you can use <code>src/examples/singly.ts</code> to find and fix the issue, and then run the tests again.</p>
<p>That's it! You've successfully built a linked list and learned how to create nodes that point to the next node and perform operations on them.</p>
<p>While singly linked lists are useful, they have a big limitation: each node only points to the next node.</p>
<p>Wouldn't it be great if nodes could also point to the previous node? This would let us do many more operations with our linked list.</p>
<p>That's exactly what you will learn in the next section.</p>
<h2 id="heading-what-is-a-doubly-linked-list">What is a Doubly Linked List?</h2>
<p>In this section, you’ll create a Doubly Linked List. It’s called "Doubly Linked" because each node points to both the next and previous nodes in the list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748530715135/52d0559e-0767-45cf-93b6-b236ba890740.png" alt="Diagram of a doubly linked list with nodes labeled A to D. Arrows indicate the &quot;next&quot; and &quot;prev&quot; connections between nodes, with Node A as the head and Node D as the tail. The tail points to NULL." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>First, let’s look at the node structure in a doubly linked list, and then you’ll implement the operations in the actual linked list.</p>
<h3 id="heading-how-to-create-a-generic-node-structure-for-a-doubly-linked-list">How to Create a Generic Node Structure for a Doubly Linked List</h3>
<p>The node structure in doubly linked lists is similar to singly linked lists, except it has an additional pointer to point to the previous node.</p>
<p>The Node structure in a doubly linked list consists of three parts:</p>
<ul>
<li><p><strong>data</strong>: Stores the node’s value.</p>
</li>
<li><p><strong>Next pointer</strong>: Links to the next node in the list or <code>null</code> if there’s no next node.</p>
</li>
<li><p><strong>Previous pointer</strong>: Links to the previous node in the list or <code>null</code> if there’s no previous node.</p>
</li>
</ul>
<p>Open <code>src/playground/doubly.ts</code> and modify the <code>N</code> class with the following code to set up the node structure:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  data: T;
  next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}
</code></pre>
<p>Here’s how the node structure works:</p>
<ul>
<li><p>It builds a <a target="_blank" href="https://www.typescriptlang.org/fr/docs/handbook/2/generics.html">generic</a> <code>Node</code>: Uses <code>&lt;T&gt;</code> to handle any data type, such as numbers or strings.</p>
</li>
<li><p>It stores the node’s value: Assigns the value to the <code>data</code> property.</p>
</li>
<li><p>It links to the next node: Sets the <code>next</code> pointer to the next node or <code>null</code> if there isn’t one.</p>
</li>
<li><p>It links to the previous node: Sets the <code>prev</code> pointer to the previous node or <code>null</code> if there isn’t one.</p>
</li>
</ul>
<p>Then, the <code>constructor</code> sets the <code>data</code> when you create a new node.</p>
<h3 id="heading-how-to-implement-a-doubly-linked-list">How to Implement a Doubly Linked List</h3>
<p>Now that the Node class is ready, you can start building the actual list.</p>
<p>Open <code>src/playground/doubly.ts</code> and take a look at the <code>DoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  data: T;
  next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> DoublyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Tail node */</span>
  <span class="hljs-keyword">public</span> tail: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** List length */</span>
  <span class="hljs-keyword">public</span> len: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/** Creates an empty list */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len = <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes and returns head node data */</span>
  deleteHead(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Removes and returns tail node data */</span>
  deleteTail(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Finds node at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(dir: <span class="hljs-string">"forward"</span> | <span class="hljs-string">"backward"</span> = <span class="hljs-string">"forward"</span>): T[] {
    <span class="hljs-keyword">return</span> [];
  }

  <span class="hljs-comment">/** Inserts node at given index */</span>
  insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
}
</code></pre>
<p>This class has two pointers, <code>head</code> and <code>tail</code>, and a variable called <code>len</code>:</p>
<ul>
<li><p><code>head</code>: This always points to the first item in your list.</p>
</li>
<li><p><code>tail</code>: This always points to the last item in your list.</p>
</li>
<li><p><code>len</code>: This represents the length of your linked list. Each time you modify the list by adding or removing a node, you need to update <code>len</code> to reflect the correct length.</p>
</li>
</ul>
<p>A valid doubly linked list will always have a <code>head</code> and a <code>tail</code>. If either the <code>head</code> or <code>tail</code> is <code>null</code>, it means the list is empty and has no nodes.</p>
<p>That's why you initially set the <code>head</code> and <code>tail</code> to <code>null</code>. When you create a list, it's empty at first. As you add a node to the list, you update the pointers to point to the new node.</p>
<p>Now, let's move on to the next section and see how you can add a node to your doubly linked list.</p>
<h3 id="heading-how-to-prepend-a-node-in-a-doubly-linked-list">How to Prepend a Node in a Doubly Linked List</h3>
<p>The goal is to add a new node to the beginning of your doubly linked list and update the <code>head</code> pointer to this new node.</p>
<p>Modify the <code>prepend</code> method in your <code>DoublyLinkedList</code> class located in <code>src/playground/doubly.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

prepend(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-built_in">this</span>.tail = newNode;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">let</span> prevHead = <span class="hljs-built_in">this</span>.head;
    newNode.next = prevHead;
    prevHead.prev = newNode;
    <span class="hljs-built_in">this</span>.head = newNode;
  }

  <span class="hljs-built_in">this</span>.len++;
}
</code></pre>
<p>The <code>data</code> prop holds the value for the new node. Here’s how <code>prepend</code> works:</p>
<ul>
<li><p>It creates a new node with the given data.</p>
</li>
<li><p>If the list is empty (<code>head</code> is <code>null</code>), it sets both the <code>head</code> and <code>tail</code> to the new node.</p>
</li>
<li><p>If the list has nodes, it points the new node’s <code>next</code> to the current <code>head</code>.</p>
</li>
<li><p>It points the current <code>head</code>’s <code>prev</code> to the new node.</p>
</li>
<li><p>It sets the <code>head</code> to the new node.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-append-a-node-in-a-doubly-linked-list">How to Append a Node in a Doubly Linked List</h3>
<p>The goal is to add a new node to the end of your doubly linked list and update the <code>tail</code> pointer to this new node.</p>
<p>Modify the append method in your <code>DoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

append(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-built_in">this</span>.tail = newNode;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">this</span>.tail!.next = newNode;
    newNode.prev = <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-built_in">this</span>.tail = newNode;
  }

  <span class="hljs-built_in">this</span>.len++;
}
</code></pre>
<p>Here’s how <code>append</code> works:</p>
<ul>
<li><p>The <code>data</code> prop holds the value for the new node.</p>
</li>
<li><p>It makes a new node with the given data.</p>
</li>
<li><p>It checks if the list is empty ( <code>head</code> is <code>null</code> ), and sets both the <code>head</code> and <code>tail</code> to the new node.</p>
</li>
<li><p>If the list has nodes, it points the current <code>tail</code>’s next to the new node.</p>
</li>
<li><p>It points the new node’s <code>prev</code> to the current tail.</p>
</li>
<li><p>It sets the <code>tail</code> to the new node.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-delete-the-head-of-a-doubly-linked-list">How to Delete the Head of a Doubly Linked List</h3>
<p>The goal is to remove the first node from your doubly linked list and return its data.</p>
<p>Modify the <code>deleteHead</code> method in your <code>DoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

deleteHead(): T | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">this</span>.head = removedItem.next;
    <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-literal">null</span>;
    removedItem.next = <span class="hljs-literal">null</span>;
  }

  <span class="hljs-built_in">this</span>.len--;

  <span class="hljs-keyword">return</span> removedItem.data;
}
</code></pre>
<p>Here’s how <code>deleteHead</code> works:</p>
<ul>
<li><p>If the list is empty, it returns <code>null</code> because there’s no node to remove.</p>
</li>
<li><p>It creates a new variable called <code>removedItem</code> and stores the <code>head</code> node in it as the item to be removed.</p>
</li>
<li><p>If the list’s length is 1, it means the list has only one node, which acts as both the <code>head</code> and <code>tail</code> of the list. In this case, it sets both the <code>head</code> and <code>tail</code> to <code>null</code>.</p>
</li>
<li><p>If the list has multiple nodes, it moves the <code>head</code> to the next node.</p>
</li>
<li><p>It sets the new <code>head</code>'s <code>prev</code> to <code>null</code> since it’s now the first node.</p>
</li>
<li><p>It clears the removed node’s <code>next</code> pointer.</p>
</li>
<li><p>It decreases the list’s length by one.</p>
</li>
<li><p>It returns the removed node’s data.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-delete-the-last-node-of-a-doubly-linked-list">How to Delete the Last Node of a Doubly Linked List</h3>
<p>The goal is to remove the last node from your doubly linked list and return its data.</p>
<p>Modify the <code>deleteTail</code> method in your <code>DoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

deleteTail(): T | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.tail) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.tail;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail.prev;
    <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-literal">null</span>;
    removedItem.prev = <span class="hljs-literal">null</span>;
  }

  <span class="hljs-built_in">this</span>.len--;

  <span class="hljs-keyword">return</span> removedItem.data;
}
</code></pre>
<p>Here’s how <code>deleteTail</code> works:</p>
<ul>
<li><p>It checks if the list is empty. If the <code>tail</code> is <code>null</code>, it returns <code>null</code> because there’s no node to remove.</p>
</li>
<li><p>It saves the <code>tail</code> node in a variable named <code>removedItem</code> as the node to be removed.</p>
</li>
<li><p>It checks if the list has one node. If the length is 1, it sets both <code>head</code> and <code>tail</code> to <code>null</code>.</p>
</li>
<li><p>If the list has multiple nodes, it moves the <code>tail</code> to the previous node.</p>
</li>
<li><p>It sets the new <code>tail</code>'s <code>next</code> to <code>null</code> since it’s now the last node.</p>
</li>
<li><p>It clears the removed node’s <code>prev</code> pointer.</p>
</li>
<li><p>It decreases the list’s length by one.</p>
</li>
<li><p>It returns the removed node’s data.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-delete-a-node-from-a-doubly-linked-list">How to Delete a Node from a Doubly Linked List</h3>
<p>The goal is to remove the first node with the given value from your doubly linked list and return <code>true</code> if successful.</p>
<p>Modify the <code>delete</code> method in your <code>DoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

<span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (current.data === data) {
    <span class="hljs-built_in">this</span>.head = current.next;
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) <span class="hljs-built_in">this</span>.head.prev = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">else</span> <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len--;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">while</span> (current.next) {
    <span class="hljs-keyword">if</span> (current.next.data === data) {
      <span class="hljs-keyword">let</span> nodeToRemove = current.next;
      current.next = nodeToRemove.next;
      <span class="hljs-keyword">if</span> (current.next) current.next.prev = current;
      <span class="hljs-keyword">else</span> <span class="hljs-built_in">this</span>.tail = current;
      nodeToRemove.next = <span class="hljs-literal">null</span>;
      nodeToRemove.prev = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.len--;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    current = current.next;
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>The <code>data</code> prop is the value to find and remove.</p>
<p>Here’s how <code>delete</code> works:</p>
<ul>
<li><p>It checks if the list is empty - if the head is <code>null</code>, returns <code>false</code> because there’s nothing to delete.</p>
</li>
<li><p>It checks if the <code>head</code> node’s value matches data and if it does, moves the <code>head</code> to the next node, sets the new <code>head</code>’s <code>prev</code> to <code>null</code> or clears the <code>tail</code> if empty, decreases the length, and returns <code>true</code>.</p>
</li>
<li><p>If the <code>head</code> doesn’t match, it creates a new pointer called <code>current</code> at the head.</p>
</li>
<li><p>It moves <code>current</code> through the list while a next node exists, checking if the next node’s value matches data.</p>
</li>
<li><p>If a match is found, it skips the next node by linking <code>current</code>’s <code>next</code> to the node after it.</p>
</li>
<li><p>It updates the next node’s <code>prev</code> to <code>current</code> or sets the <code>tail</code> to <code>current</code> if it’s the last node, clears the removed node’s pointers, decreases the length, and returns <code>true</code>.</p>
</li>
<li><p>If no match is found, it moves <code>current</code> to the next node and keeps checking.</p>
</li>
<li><p>If you reach the end without a match, it returns false.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node.</p>
<h3 id="heading-how-to-find-a-node-in-a-doubly-linked-list">How to Find a Node in a Doubly Linked List</h3>
<p>The goal is to find the node at a specific position in your doubly linked list.</p>
<p>Modify the <code>find</code> method in your <code>DoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt;= <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">if</span> (idx &lt;= <span class="hljs-built_in">this</span>.len / <span class="hljs-number">2</span>) {
    current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; idx; i++) {
      current = current!.next;
    }
  } <span class="hljs-keyword">else</span> {
    current = <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-built_in">this</span>.len - <span class="hljs-number">1</span>; i &gt; idx; i--) {
      current = current?.prev ?? <span class="hljs-literal">null</span>;
    }
  }

  <span class="hljs-keyword">return</span> current;
}
</code></pre>
<p>The <code>idx</code> prop is the position in the list, starting at 0.</p>
<p>Here’s how <code>find</code> works:</p>
<ul>
<li><p>It checks if the index is valid. If <code>idx</code> is negative or too large, it returns <code>null</code> because no node exists.</p>
</li>
<li><p>It starts a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It checks if <code>idx</code> is in the first half of the list. If it is, it moves <code>current</code> forward <code>idx</code> times using the <code>next</code> pointer.</p>
</li>
<li><p>If <code>idx</code> is in the second half, it starts <code>current</code> at the <code>tail</code> and moves backward to the position using the <code>prev</code> pointer.</p>
</li>
<li><p>It returns the <code>current</code> node, which is at the given index, or <code>null</code> if the list is empty.</p>
</li>
</ul>
<p>This runs in O(n) time because you may move through half the list to find the node.</p>
<h3 id="heading-how-to-traverse-a-doubly-linked-list">How to Traverse a Doubly Linked List</h3>
<p>The goal is to return an array of all node data in your doubly linked list, either forward or backward. Modify the traverse method in your <code>DoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

traverse(dir: <span class="hljs-string">"forward"</span> | <span class="hljs-string">"backward"</span> = <span class="hljs-string">"forward"</span>): T[] {
  <span class="hljs-keyword">const</span> isForward = dir === <span class="hljs-string">"forward"</span>;
  <span class="hljs-keyword">let</span> current = isForward ? <span class="hljs-built_in">this</span>.head : <span class="hljs-built_in">this</span>.tail;
  <span class="hljs-keyword">const</span> result: T[] = [];

  <span class="hljs-keyword">while</span> (current) {
    result.push(current.data);
    current = isForward ? current.next : current.prev;
  }

  <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>The <code>dir</code> prop sets whether to go forward (from <code>head</code> to <code>tail</code>) or backward (from <code>tail</code> to <code>head</code>).</p>
<p>Here’s how <code>traverse</code> works:</p>
<ul>
<li><p>It checks the direction and sets a flag to true if moving forward.</p>
</li>
<li><p>It starts a new pointer called <code>current</code> at the <code>head</code> if forward, or the <code>tail</code> if backward.</p>
</li>
<li><p>It creates an empty array to store the node data.</p>
</li>
<li><p>While <code>current</code> exists, it adds its data to the array.</p>
</li>
<li><p>It moves <code>current</code> to the next node if forward, or the previous node if backward.</p>
</li>
<li><p>It returns the array with all node data.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to visit every node in the list.</p>
<h3 id="heading-how-to-insert-a-node-at-a-specific-position-in-a-doubly-linked-list"><strong>How to Insert a Node at a Specific Position in a Doubly Linked List</strong></h3>
<p>The goal is to add a new node at a specific index in your doubly linked list.</p>
<p>Modify the <code>insertAt</code> method in your <code>DoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>

insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt; <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">this</span>.prepend(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">if</span> (idx === <span class="hljs-built_in">this</span>.len) {
    <span class="hljs-built_in">this</span>.append(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.find(idx);

  <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  newNode.next = current;
  newNode.prev = current?.prev ?? <span class="hljs-literal">null</span>;
  current.prev!.next = newNode;
  current.prev = newNode;

  <span class="hljs-built_in">this</span>.len++;

  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>The <code>idx</code> prop is the position in the list, and <code>data</code> is the value.</p>
<p>Here’s how <code>insertAt</code> works:</p>
<ul>
<li><p>It checks if the index is invalid, if <code>idx</code> is negative or greater than the list’s length, returns <code>false</code>.</p>
</li>
<li><p>If the index is 0, you are adding the new node at the beginning. Simply call <code>prepend</code> to add the node at the start and return <code>true</code>.</p>
</li>
<li><p>If the index is equal to the list's length, you are adding the new node to the end of the list. In this case, you can call <code>append</code> to add the node at the end and return <code>true</code>.</p>
</li>
<li><p>If the previous conditions are not met, it creates a new node with the given data.</p>
</li>
<li><p>It finds the node at the given index using the <code>find</code> method and stores it as <code>current</code>.</p>
</li>
<li><p>If no node is found at the index, it returns <code>false</code>.</p>
</li>
<li><p>It points the new node’s <code>next</code> to <code>current</code>.</p>
</li>
<li><p>It points the new node’s <code>prev</code> to <code>current</code>’s previous node.</p>
</li>
<li><p>It points the previous node’s <code>next</code> to the new node.</p>
</li>
<li><p>It points <code>current</code>’s <code>prev</code> to the new node.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
<li><p>It returns <code>true</code> to show the node was successfully inserted.</p>
</li>
</ul>
<p>This runs in O(n) time because finding the index may require traversing the list.</p>
<h3 id="heading-how-to-test-your-doubly-linked-list">How to Test Your Doubly Linked List</h3>
<p>Awesome, what great progress! You've successfully implemented your doubly linked list. Here's what the final implementation should look like:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/doubly.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  data: T;
  next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-comment">/** Doubly linked list implementation */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> DoublyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Tail node */</span>
  <span class="hljs-keyword">public</span> tail: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** List length */</span>
  <span class="hljs-keyword">public</span> len: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/** Creates an empty list */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len = <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">let</span> prevHead = <span class="hljs-built_in">this</span>.head;
      newNode.next = prevHead;
      prevHead.prev = newNode;
      <span class="hljs-built_in">this</span>.head = newNode;
    }

    <span class="hljs-built_in">this</span>.len++;
  }

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail = newNode;
    }

    <span class="hljs-built_in">this</span>.len++;
  }

  <span class="hljs-comment">/** Removes and returns head node data */</span>
  deleteHead(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.head = removedItem.next;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-literal">null</span>;
      removedItem.next = <span class="hljs-literal">null</span>;
    }

    <span class="hljs-built_in">this</span>.len--;

    <span class="hljs-keyword">return</span> removedItem.data;
  }

  <span class="hljs-comment">/** Removes and returns tail node data */</span>
  deleteTail(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.tail) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.tail;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail.prev;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-literal">null</span>;
      removedItem.prev = <span class="hljs-literal">null</span>;
    }

    <span class="hljs-built_in">this</span>.len--;

    <span class="hljs-keyword">return</span> removedItem.data;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (current.data === data) {
      <span class="hljs-built_in">this</span>.head = current.next;
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head) <span class="hljs-built_in">this</span>.head.prev = <span class="hljs-literal">null</span>;
      <span class="hljs-keyword">else</span> <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.len--;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">while</span> (current.next) {
      <span class="hljs-keyword">if</span> (current.next.data === data) {
        <span class="hljs-keyword">let</span> nodeToRemove = current.next;
        current.next = nodeToRemove.next;
        <span class="hljs-keyword">if</span> (current.next) current.next.prev = current;
        <span class="hljs-keyword">else</span> <span class="hljs-built_in">this</span>.tail = current;
        nodeToRemove.next = <span class="hljs-literal">null</span>;
        nodeToRemove.prev = <span class="hljs-literal">null</span>;
        <span class="hljs-built_in">this</span>.len--;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }
      current = current.next;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Finds node at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt;= <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">if</span> (idx &lt;= <span class="hljs-built_in">this</span>.len / <span class="hljs-number">2</span>) {
      current = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; idx; i++) {
        current = current!.next;
      }
    } <span class="hljs-keyword">else</span> {
      current = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-built_in">this</span>.len - <span class="hljs-number">1</span>; i &gt; idx; i--) {
        current = current?.prev ?? <span class="hljs-literal">null</span>;
      }
    }

    <span class="hljs-keyword">return</span> current;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(dir: <span class="hljs-string">"forward"</span> | <span class="hljs-string">"backward"</span> = <span class="hljs-string">"forward"</span>): T[] {
    <span class="hljs-keyword">const</span> isForward = dir === <span class="hljs-string">"forward"</span>;
    <span class="hljs-keyword">let</span> current = isForward ? <span class="hljs-built_in">this</span>.head : <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-keyword">const</span> result: T[] = [];

    <span class="hljs-keyword">while</span> (current) {
      result.push(current.data);
      current = isForward ? current.next : current.prev;
    }

    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-comment">/** Inserts node at given index */</span>
  insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt; <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">this</span>.prepend(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">if</span> (idx === <span class="hljs-built_in">this</span>.len) {
      <span class="hljs-built_in">this</span>.append(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.find(idx);

    <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    newNode.next = current;
    newNode.prev = current?.prev ?? <span class="hljs-literal">null</span>;
    current.prev!.next = newNode;
    current.prev = newNode;

    <span class="hljs-built_in">this</span>.len++;

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>Run the following command to make sure that your implementation is correct:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file doubly
</code></pre>
<p>If the tests run successfully, you're good to go! If any tests fail, check <code>src/examples/doubly.ts</code>, fix the issue, and run the tests again.</p>
<p>You've learned how to implement a linked node with two pointers. Doubly linked lists are useful in many scenarios, but like singly linked lists, they have a limitation you need to consider.</p>
<p>Let's say you have a music playlist, and every time you reach the end, you want to loop back to the first song instead of stopping.</p>
<p>In both singly and doubly linked lists, once you reach the end, there's no way to loop back to the first item because the last node points to <code>null</code>. So, what will you do if you want to create a music playlist using linked lists?</p>
<p>That's what you'll learn in the next section of this tutorial!</p>
<h2 id="heading-what-is-a-circular-linked-list">What is a Circular Linked List?</h2>
<p>So far, you've learned about singly and doubly linked lists, where the last item always points to <code>null</code>.</p>
<p>Sometimes, you need to go back to the first item after reaching the last one. In this case, the <code>tail</code>'s <code>next</code> pointer should point to the <code>head</code> instead of <code>null</code>.</p>
<p>This is what a circular linked list is. In circular linked lists, the <code>tail</code> points to the <code>head</code>, letting you keep going through the list without stopping.</p>
<p>In the next 2 sections, you'll learn about two types of circular linked lists:</p>
<ul>
<li><p><strong>Circular Singly Linked List:</strong> Each node has one pointer to the next node, and the <code>tail</code> always points to the <code>head</code>.</p>
</li>
<li><p><strong>Circular Doubly Linked List:</strong> Each node has two pointers to the next and previous nodes. The <code>tail</code> points to the <code>head</code> as its next node, and the <code>head</code> points to the <code>tail</code> as its previous node.</p>
</li>
</ul>
<p>Now, let's dive deeper and learn how to create each of these lists.</p>
<h2 id="heading-what-is-a-circular-singly-linked-list">What is a <strong>Circular Singly</strong> Linked List?</h2>
<p>In a circular singly linked list, each node has only one pointer that points to the next node in the list. The main difference between a singly linked list and a circular singly linked list is the <code>tail</code> node.</p>
<p>In a circular singly linked list, the <code>tail</code> always points to the <code>head</code>, forming a circle that allows continuous looping through the list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748531277470/15e7aafc-e499-47ec-a0b7-2b0e61867162.png" alt="Diagram of a circular singly linked list with nodes labeled A, B, C, and D. Arrows indicate the &quot;next&quot; pointers, forming a loop. The head points to Node A, and the tail points to Node D." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now, let's look at the node structure in a circular singly linked list.</p>
<h3 id="heading-how-to-create-a-generic-node-structure-for-a-circular-singly-linked-list">How to Create a Generic Node Structure for a Circular Singly Linked List</h3>
<p>The <code>Node</code> structure in a circular singly linked list has two parts: the data and a pointer to the next node.</p>
<p>The <code>data</code> property holds the node's value, and <code>next</code> points to the next node in the list.</p>
<p>Open <code>src/playground/circular-1.ts</code> and modify the <code>N</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/** Node for circular singly linked list */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node data */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given data */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
  }
}
</code></pre>
<p>Here’s how the node structure works:</p>
<ul>
<li><p>It builds a <a target="_blank" href="https://www.typescriptlang.org/fr/docs/handbook/2/generics.html">generic</a> Node: Uses &lt;T&gt; to handle any data type, such as numbers or strings.</p>
</li>
<li><p>It stores the node’s value: Assigns the value to the data property.</p>
</li>
<li><p>It links to the next node: Sets the <code>next</code> pointer to the next node, <code>null</code> only during initialization. In a valid circular list, next always connects to a node.</p>
</li>
<li><p>It initializes the node: Takes a value in the constructor and assigns it to data.</p>
</li>
</ul>
<p>In a valid circular linked list, <code>next</code> never stays <code>null</code>.</p>
<h3 id="heading-how-to-implement-a-circular-singly-linked-list">How to Implement a Circular Singly Linked List</h3>
<p>Once you have created your Node structure, you can start implementing the linked list.</p>
<p>To get started, let’s open <code>src/playground/circular-1.ts</code>, where you'll find the <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  data: T;
  next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularSinglyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes head node */</span>
  deleteHead(): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes tail node */</span>
  deleteTail(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Finds data at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(): T[] {
    <span class="hljs-keyword">return</span> [];
  }
}
</code></pre>
<p>You will complete each method by the end of this section.</p>
<p>Like in earlier implementations, <code>head</code> will point to the first item in the list. If it's <code>null</code>, the list is empty.</p>
<p>Now, let's go to the first method and learn how to add a node to the start of a circular linked list.</p>
<h3 id="heading-how-to-prepend-a-node-in-a-circular-singly-linked-list">How to Prepend a Node in a Circular Singly Linked List</h3>
<p>The goal is to add a new node to the beginning of your circular singly linked list and update the head pointer to this new node.</p>
<p>Modify the prepend method in your <code>CircularSinglyLinkedList</code> class located in <code>src/playground/circular-singly.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

prepend(data: T) {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    newNode.next = newNode;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
      <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
      last = last.next;
    }

    last.next = newNode;
    newNode.next = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-built_in">this</span>.head = newNode;
  }
}
</code></pre>
<p>The <code>data</code> prop holds the value for the new node.</p>
<p>Here’s how <code>prepend</code> works:</p>
<ul>
<li><p>It creates a new node with the given value.</p>
</li>
<li><p>Checks if the list is empty. If the <code>head</code> is <code>null</code>, it sets the head to the new node and points its <code>next</code> to itself to form a single-node circle.</p>
</li>
<li><p>If the list has nodes, it finds the last node by moving through the list until it reaches the node whose <code>next</code> points to the head.</p>
</li>
<li><p>It points the last node’s <code>next</code> to the new node.</p>
</li>
<li><p>It points the new node’s <code>next</code> to the current <code>head</code>.</p>
</li>
<li><p>It sets the <code>head</code> to the new node.</p>
</li>
<li><p>Now, the new node is the head, and you’ve maintained the circular structure.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the last node.</p>
<h3 id="heading-how-to-append-a-node-in-a-circular-singly-linked-list">How to Append a Node in a Circular Singly Linked List</h3>
<p>The goal is to add a new node to the end of your circular singly linked list and maintain the circular structure.</p>
<p>Let’s modify the append method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

append(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    newNode.next = <span class="hljs-built_in">this</span>.head;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
      <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
      last = last.next;
    }

    last.next = newNode;
    newNode.next = <span class="hljs-built_in">this</span>.head;
  }
}
</code></pre>
<p>The <code>data</code> prop holds the value for the new node.</p>
<p>Here’s how <code>append</code> works:</p>
<ul>
<li><p>It creates a new node with the given value.</p>
</li>
<li><p>It checks if the list is empty. If the <code>head</code> is <code>null</code>, it sets the <code>head</code> to the new node and points its <code>next</code> to itself to form a single-node circle.</p>
</li>
<li><p>If the list has nodes, it finds the last node by moving through the list until it reaches the node whose <code>next</code> points to the <code>head</code>.</p>
</li>
<li><p>It points the last node’s <code>next</code> to the new node.</p>
</li>
<li><p>It points the new node’s <code>next</code> to the <code>head</code> to keep the list circular.</p>
</li>
<li><p>Now, the new node is at the end, and you’ve maintained the circular structure.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the last node.</p>
<h3 id="heading-how-to-delete-the-head-of-a-circular-singly-linked-list">How to Delete the Head of a Circular Singly Linked List</h3>
<p>The goal is to remove the first node from your circular singly linked list and update the <code>head</code> pointer.</p>
<p>Modify the <code>deleteHead</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

deleteHead(): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.next === <span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
    <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
    last = last.next;
  }

  <span class="hljs-keyword">let</span> newHead = <span class="hljs-built_in">this</span>.head.next;
  last.next = newHead;
  <span class="hljs-built_in">this</span>.head = newHead;
}
</code></pre>
<p>Here’s how <code>deleteHead</code> works:</p>
<ul>
<li><p>It checks if the list is empty and stops the operation if the <code>head</code> is <code>null</code> because there’s no node to remove.</p>
</li>
<li><p>It checks if the list has one node: if the <code>head</code>'s next points to itself, it sets the <code>head</code> to <code>null</code> to empty the list.</p>
</li>
<li><p>If the list has multiple nodes, it finds the last node by moving through the list until it reaches the node whose next points to the <code>head</code>.</p>
</li>
<li><p>It sets the current <code>head</code>’s <code>next</code> node as the new <code>head</code>.</p>
</li>
<li><p>It points the tail node’s <code>next</code> to the new head to keep the list circular.</p>
</li>
<li><p>It sets the head to the new head.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the last node.</p>
<h3 id="heading-how-to-delete-the-last-node-of-a-circular-singly-linked-list">How to Delete the Last Node of a Circular Singly Linked List</h3>
<p>The goal is to remove the last node from your circular singly linked list and maintain the circular structure.</p>
<p>Modify the <code>deleteTail</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

deleteTail(): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.next === <span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">let</span> current: N&lt;T&gt; = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">while</span> (current.next !== <span class="hljs-built_in">this</span>.head) {
    prev = current;
    current = current.next!;
  }

  prev!.next = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>Here’s how deleteTail works:</p>
<ul>
<li><p>It checks if the list is empty. If the <code>head</code> is <code>null</code>, it returns <code>false</code> because there’s no node to remove.</p>
</li>
<li><p>It checks if the list has one node. If the <code>head</code>’s next points to itself, it sets the <code>head</code> to <code>null</code> and returns <code>true</code>.</p>
</li>
<li><p>If the list has multiple nodes, it starts a new pointer called <code>current</code> at the <code>head</code> and a <code>prev</code> pointer at <code>null</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list until its next points to the <code>head</code>, keeping <code>prev</code> one node behind.</p>
</li>
<li><p>It points <code>prev</code>’s <code>next</code> to the <code>head</code> to skip the last node and keep the list circular.</p>
</li>
<li><p>It returns <code>true</code> to show the tail was removed.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the last node.</p>
<h3 id="heading-how-to-delete-a-node-from-a-circular-singly-linked-list">How to Delete a Node from a Circular Singly Linked List</h3>
<p>The goal is to remove the first node with the given value from your circular singly linked list and return <code>true</code> if successful.</p>
<p>Modify the <code>delete</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

<span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.data === data) {
    <span class="hljs-built_in">this</span>.deleteHead();
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">let</span> current: N&lt;T&gt; = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">if</span> (current.data === data) {
      prev!.next = current.next;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    prev = current;
    current = current.next!;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>The data prop is the value to find and remove.</p>
<p>You must use a do-while loop instead of a simple while loop in the method because it ensures you always process the <code>head</code> node's data at least once before checking if you've returned to the <code>head</code>.</p>
<p>In a circular singly linked list, you start at the <code>head</code> and keep moving to the next node until you come back to the head.</p>
<p>A simple while loop might skip the <code>head</code> if checked first, but a do-while loop makes sure the <code>head</code>'s data is included.</p>
<p>Here’s how delete works:</p>
<ul>
<li><p>It checks if the list is empty. If the <code>head</code> is <code>null</code>, it returns <code>false</code> because there’s nothing to <code>delete</code>.</p>
</li>
<li><p>It checks if the <code>head</code> node’s value matches data. If it does, it calls <code>deleteHead</code> to remove the head and returns <code>true</code>.</p>
</li>
<li><p>If the <code>head</code> doesn’t match, it starts a new pointer called <code>current</code> at the <code>head</code> and a <code>prev</code> pointer at <code>null</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list, keeping <code>prev</code> one node behind, until it circles back to the head.</p>
</li>
<li><p>If current’s value matches data, it links <code>prev</code>’s <code>next</code> to <code>current</code>’s <code>next</code> to skip the matched node.</p>
</li>
<li><p>It returns <code>true</code> if a match is removed, or <code>false</code> if it finds no match after a full loop.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node.</p>
<h3 id="heading-how-to-find-a-node-in-a-circular-singly-linked-list">How to Find a Node in a Circular Singly Linked List</h3>
<p>The goal is to find the data at a specific index in your circular singly linked list.</p>
<p>Modify the <code>find</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

find(idx: <span class="hljs-built_in">number</span>): T | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head || idx &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">if</span> (!current.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);

    <span class="hljs-keyword">if</span> (count === idx) {
      <span class="hljs-keyword">return</span> current.data;
    }

    count++;
    current = current.next;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>The <code>idx</code> prop is the position in the list.</p>
<p>Here’s how find works:</p>
<ul>
<li><p>It checks if the list is empty or the index is negative. If so, it returns <code>null</code> because no data exists.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code> and set a <code>counter</code> to 0.</p>
</li>
<li><p>It moves <code>current</code> through the list, checking each node until it circles back to the <code>head</code>.</p>
</li>
<li><p>If the <code>counter</code> equals <code>idx</code>, it returns the <code>current</code> node’s data.</p>
</li>
<li><p>If not, it increases the <code>counter</code> and moves <code>current</code> to the next node.</p>
</li>
<li><p>If you circle back to the <code>head</code> without finding the index, it returns <code>null</code>.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the index.</p>
<h3 id="heading-how-to-traverse-a-circular-singly-linked-list">How to Traverse a Circular Singly Linked List</h3>
<p>The goal is to return an array of all node data in your circular singly linked list.</p>
<p>Modify the <code>traverse</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

traverse(): T[] {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> [];
  <span class="hljs-keyword">const</span> result: T[] = [];

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">do</span> {
    result.push(current.data);
    current = current.next!;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>Here’s how traverse works:</p>
<ul>
<li><p>It checks if the list is empty. If the <code>head</code> is <code>null</code>, it returns an empty array.</p>
</li>
<li><p>It creates an empty array to store the node data.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list, adding each node’s data to the array.</p>
</li>
<li><p>It continues moving <code>current</code> to the next node until you circle back to the <code>head</code>.</p>
</li>
<li><p>It returns the array with all node data.</p>
</li>
</ul>
<p>This runs in O(n) time because you need to visit every node in the list.</p>
<h3 id="heading-how-to-insert-a-node-at-a-specific-position-in-a-circular-singly-linked-list"><strong>How to Insert a Node at a Specific Position in a Circular Singly Linked List</strong></h3>
<p>The goal is to add a new node at a specific index in your circular singly linked list.</p>
<p>Modify the <code>insertAt</code> method in your <code>CircularSinglyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-1.ts</span>

insertAt(data: T, idx: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">this</span>.prepend(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">this</span>.prepend(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">if</span> (count === idx) {
      <span class="hljs-keyword">const</span> newN = <span class="hljs-keyword">new</span> N(data);
      newN.next = current;
      prev!.next = newN;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    prev = current;
    current = current!.next;
    count++;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">if</span> (count === idx) {
    <span class="hljs-built_in">this</span>.append(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>The <code>data</code> prop is the value, and <code>idx</code> is the position in the list.</p>
<p>Here’s how <code>insertAt</code> works:</p>
<ul>
<li><p>If the index is negative, it returns <code>false</code> because it’s invalid.</p>
</li>
<li><p>If the index is 0, it calls <code>prepend</code> to add the node at the start and returns <code>true</code>.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>, a <code>prev</code> pointer at <code>null</code>, and a counter at <code>0</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list, keeping <code>prev</code> one node behind, until you circle back to the <code>head</code>.</p>
</li>
<li><p>If the counter equals <code>idx</code>, it creates a new node, point its <code>next</code> to <code>current</code>, points <code>prev</code>’s <code>next</code> to the new node, and returns <code>true</code>.</p>
</li>
<li><p>If you circle back to the head and the counter equals <code>idx</code>, it calls <code>append</code> to add the node at the end and returns <code>true</code>.</p>
</li>
<li><p>Finally, if the index is not found, it returns <code>false</code>.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the index.</p>
<h3 id="heading-how-to-test-your-circular-singly-linked-list">How to Test Your Circular Singly Linked List</h3>
<p>Perfect! You are done with the circular singly linked list and now you are ready to test your implementation.</p>
<p>Your final implementation should look something like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/** Node for circular singly linked list */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node data */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given data */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-comment">/** Circular singly linked list implementation */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularSinglyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T) {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      newNode.next = newNode;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

      <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
        <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
        last = last.next;
      }

      last.next = newNode;
      newNode.next = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-built_in">this</span>.head = newNode;
    }
  }

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      newNode.next = <span class="hljs-built_in">this</span>.head;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

      <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
        <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
        last = last.next;
      }

      last.next = newNode;
      newNode.next = <span class="hljs-built_in">this</span>.head;
    }
  }

  <span class="hljs-comment">/** Removes head node */</span>
  deleteHead(): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span>;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.next === <span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> last = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">while</span> (last.next !== <span class="hljs-built_in">this</span>.head) {
      <span class="hljs-keyword">if</span> (!last.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);
      last = last.next;
    }

    <span class="hljs-keyword">let</span> newHead = <span class="hljs-built_in">this</span>.head.next;
    last.next = newHead;
    <span class="hljs-built_in">this</span>.head = newHead;
  }

  <span class="hljs-comment">/** Removes tail node */</span>
  deleteTail(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.next === <span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">let</span> current: N&lt;T&gt; = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">while</span> (current.next !== <span class="hljs-built_in">this</span>.head) {
      prev = current;
      current = current.next!;
    }

    prev!.next = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.head.data === data) {
      <span class="hljs-built_in">this</span>.deleteHead();
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">let</span> current: N&lt;T&gt; = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">do</span> {
      <span class="hljs-keyword">if</span> (current.data === data) {
        prev!.next = current.next;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }

      prev = current;
      current = current.next!;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Finds data at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head || idx &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">do</span> {
      <span class="hljs-keyword">if</span> (!current.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);

      <span class="hljs-keyword">if</span> (count === idx) {
        <span class="hljs-keyword">return</span> current.data;
      }

      count++;
      current = current.next;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(): T[] {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> [];
    <span class="hljs-keyword">const</span> result: T[] = [];

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">do</span> {
      result.push(current.data);
      current = current.next!;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-comment">/** Inserts node at given index */</span>
  insertAt(data: T, idx: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">this</span>.prepend(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">this</span>.prepend(data);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }
      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-keyword">let</span> current: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">let</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">do</span> {
      <span class="hljs-keyword">if</span> (count === idx) {
        <span class="hljs-keyword">const</span> newN = <span class="hljs-keyword">new</span> N(data);
        newN.next = current;
        prev!.next = newN;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }
      prev = current;
      current = current!.next;
      count++;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">if</span> (count === idx) {
      <span class="hljs-built_in">this</span>.append(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
}
</code></pre>
<p>Now, let’s run the following command to test the linked list:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file circular-1
</code></pre>
<p>If the tests run successfully, you're all set! If any tests fail, check <code>src/examples/circular-1.ts</code>, fix the issue, and run the tests again.</p>
<p>That's it, you've completed your first circular linked list implementation.</p>
<p>In the last section, you'll learn how to create a circular linked list with two pointers instead of one.</p>
<h2 id="heading-what-is-a-circular-doubly-linked-list">What is a <strong>Circular Doubly</strong> Linked List?</h2>
<p>A circular doubly linked list forms a loop where nodes connect to both the next and previous nodes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748531479718/6eeb89a6-ee2a-4e24-a2c5-e4c798e65ce2.png" alt="Diagram of a Circular Doubly Linked List with nodes labeled A, B, C, and D, showing next and prev pointers. Node A is connected to Head, and Node D is connected to Tail. Links form a circular structure." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The <code>head</code> links back to the <code>tail</code>, and the <code>tail</code> to the <code>head</code>, so you can have endless navigation in either direction.</p>
<h3 id="heading-how-to-create-a-generic-node-structure-for-a-circular-doubly-linked-list">How to Create a Generic Node Structure for a Circular Doubly Linked List</h3>
<p>The <code>Node</code> structure in a circular doubly linked list has three parts: the data, a pointer to the next node, and a pointer to the previous node.</p>
<p>The <code>data</code> property holds the node’s value, <code>next</code> points to the next node, and <code>prev</code> points to the previous node in the list.</p>
<p>Open <code>src/playground/circular-2.ts</code> and modify the <code>N</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

<span class="hljs-comment">/** Node for circular doubly linked list */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node data */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Previous node reference */</span>
  <span class="hljs-keyword">public</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given data */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}
</code></pre>
<p>Here’s how the node structure works:</p>
<ul>
<li><p>It builds a <a target="_blank" href="https://www.typescriptlang.org/fr/docs/handbook/2/generics.html">generic</a> <code>Node</code>: Uses <code>&lt;T&gt;</code> to handle any data type.</p>
</li>
<li><p>It stores the node’s value: Assigns the value to the <code>data</code> property.</p>
</li>
<li><p>It links to the next node: Sets the <code>next</code> pointer to the next node, <code>null</code> only during initialization. In a valid circular list, <code>next</code> always connects to a node.</p>
</li>
<li><p>It links to the previous node: Sets the <code>prev</code> pointer to the previous node, <code>null</code> only during initialization. In a valid circular list, <code>prev</code> always connects to a node.</p>
</li>
<li><p>It initializes the node: Takes a value in the constructor and assigns it to <code>data</code>.</p>
</li>
</ul>
<p>In a valid circular doubly linked list, <code>next</code> and <code>prev</code> never stay <code>null</code>.</p>
<h3 id="heading-how-to-implement-a-circular-doubly-linked-list">How to Implement a Circular Doubly Linked List</h3>
<p>You’ve created the <code>Node</code> structure for your circular doubly linked list. Now, you can start building the linked list itself. To get started, open <code>src/playground/circular-2.ts</code>, where you’ll find the <code>CircularDoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node data */</span>
  <span class="hljs-keyword">public</span> data: T;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Previous node reference */</span>
  <span class="hljs-keyword">public</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given data */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularDoublyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Tail node */</span>
  <span class="hljs-keyword">public</span> tail: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** List length */</span>
  <span class="hljs-keyword">public</span> len: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/** Creates an empty list */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len = <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes and returns tail node data */</span>
  deleteTail(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {}

  <span class="hljs-comment">/** Removes and returns head node data */</span>
  deleteHead(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Finds node at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(): T[] {
    <span class="hljs-keyword">return</span> [];
  }

  <span class="hljs-comment">/** Inserts node at given index */</span>
  insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
}
</code></pre>
<p>The <code>head</code> points to the first node and links backward to the tail to form a circular loop. It is <code>null</code> when the list is empty.</p>
<p>The <code>tail</code> points to the last node and links forward to the <code>head</code> to complete the circle. It is also <code>null</code> when empty.</p>
<p>The length, <code>len</code>, tracks the number of nodes. It starts at 0 and changes as you add or remove nodes.</p>
<p>Now, let’s move to the first method and learn how to add a node to the start of a circular doubly linked list.</p>
<h3 id="heading-how-to-prepend-a-node-in-a-circular-doubly-linked-list">How to Prepend a Node in a Circular Doubly Linked List</h3>
<p>The goal is to add a new node to the beginning of your circular doubly linked list and update the head pointer to this new node.</p>
<p>Modify the prepend method in your <code>CircularDoublyLinkedList</code> class located in <code>src/playground/circular-2.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

prepend(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-built_in">this</span>.tail = newNode;
    newNode.next = newNode;
    newNode.prev = newNode;
  } <span class="hljs-keyword">else</span> {
    newNode.next = <span class="hljs-built_in">this</span>.head;
    newNode.prev = <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-built_in">this</span>.head!.prev = newNode;
    <span class="hljs-built_in">this</span>.tail!.next = newNode;
    <span class="hljs-built_in">this</span>.head = newNode;
  }

  <span class="hljs-built_in">this</span>.len++;
}
</code></pre>
<p>The <code>data</code> prop holds the value for the new node.</p>
<p>Here’s how <code>prepend</code> works:</p>
<ul>
<li><p>It creates a new node with the given data.</p>
</li>
<li><p>it checks if the list is empty. If the head is <code>null</code>, it sets both <code>head</code> and <code>tail</code> to the new node and links its next and prev to itself to form a single-node circle.</p>
</li>
<li><p>If the list has nodes, it points the new node’s <code>next</code> to the current <code>head</code> and its <code>prev</code> to the current <code>tail</code>.</p>
</li>
<li><p>It points the current <code>head</code>’s <code>prev</code> to the new node.</p>
</li>
<li><p>It points the current <code>tail</code>’s <code>next</code> to the new node to keep the list circular.</p>
</li>
<li><p>It sets the <code>head</code> to the new node.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-append-a-node-in-a-circular-doubly-linked-list">How to Append a Node in a Circular Doubly Linked List</h3>
<p>The goal is to add a new node to the end of your circular doubly linked list and update the <code>tail</code> pointer to this new node.</p>
<p>Modify the append method in your <code>CircularDoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

append(data: T): <span class="hljs-built_in">void</span> {
  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
    <span class="hljs-built_in">this</span>.head = newNode;
    <span class="hljs-built_in">this</span>.tail = newNode;
    newNode.next = newNode;
    newNode.prev = newNode;
  } <span class="hljs-keyword">else</span> {
    newNode.next = <span class="hljs-built_in">this</span>.head;
    newNode.prev = <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-built_in">this</span>.tail!.next = newNode;
    <span class="hljs-built_in">this</span>.head!.prev = newNode;
    <span class="hljs-built_in">this</span>.tail = newNode;
  }

  <span class="hljs-built_in">this</span>.len++;
}
</code></pre>
<p>The data prop holds the value for the new node, like a number or string.</p>
<p>Here’s how <code>append</code> works:</p>
<ul>
<li><p>It makes a new node with the given value.</p>
</li>
<li><p>If the list is empty, then it sets both <code>head</code> and <code>tail</code> to the new node, and links its <code>next</code> and <code>prev</code> to itself to form a single-node circle.</p>
</li>
<li><p>If the list has nodes, it points the new node’s next to the <code>head</code> to maintain the circular loop.</p>
</li>
<li><p>It points the new node’s <code>prev</code> to the current <code>tail</code>.</p>
</li>
<li><p>It points the current <code>tail</code>’s next to the new node.</p>
</li>
<li><p>It points the <code>head</code>’s prev to the new node to complete the circle.</p>
</li>
<li><p>It sets the <code>tail</code> to the new node.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-delete-the-last-node-of-a-circular-doubly-linked-list">How to Delete the Last Node of a Circular Doubly Linked List</h3>
<p>The goal is to remove the last node from your circular doubly linked list and return its data.</p>
<p>Modify the <code>deleteTail</code> method in your <code>CircularDoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

deleteTail(): T | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.tail) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.tail;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail.prev;
    <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
  }

  removedItem.next = <span class="hljs-literal">null</span>;
  removedItem.prev = <span class="hljs-literal">null</span>;
  <span class="hljs-built_in">this</span>.len--;

  <span class="hljs-keyword">return</span> removedItem.data;
}
</code></pre>
<p>Here’s how <code>deleteTail</code> works:</p>
<ul>
<li><p>If the list is empty, then it returns <code>null</code> because there’s no node to remove.</p>
</li>
<li><p>It declares a variable called <code>removedItem</code> and stores the <code>tail</code> node in it to keep track of the node you want to remove.</p>
</li>
<li><p>It checks if the list has one node. If the length is 1, it sets both <code>head</code> and <code>tail</code> to <code>null</code>.</p>
</li>
<li><p>If the list has multiple nodes, it moves the <code>tail</code> to the previous node.</p>
</li>
<li><p>It points the new <code>tail</code>’s <code>next</code> to the <code>head</code> to keep the circular loop.</p>
</li>
<li><p>It points the <code>head</code>’s <code>prev</code> to the new <code>tail</code> to maintain the circle.</p>
</li>
<li><p>It clears the removed node’s <code>next</code> and <code>prev</code> pointers.</p>
</li>
<li><p>It decreases the list’s length by one.</p>
</li>
<li><p>It returns the removed node’s data.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-delete-the-head-of-a-circular-doubly-linked-list">How to Delete the Head of a Circular Doubly Linked List</h3>
<p>The goal is to remove the first node from your circular doubly linked list and return its data.</p>
<p>Modify the deleteHead method in your <code>CircularDoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

deleteHead(): T | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">this</span>.head = removedItem.next;
    <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
    <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
  }

  <span class="hljs-built_in">this</span>.len--;
  removedItem.next = <span class="hljs-literal">null</span>;
  removedItem.prev = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">return</span> removedItem.data;
}
</code></pre>
<p>Here’s how <code>deleteHead</code> works:</p>
<ul>
<li><p>If the list is empty then it returns <code>null</code> because there’s no node to remove.</p>
</li>
<li><p>It declares a variable called <code>removedItem</code> and stores the <code>head</code> node in it to keep track of the node you want to remove.</p>
</li>
<li><p>It checks if the list has one node. If the length is 1, it sets both <code>head</code> and <code>tail</code> to <code>null</code>.</p>
</li>
<li><p>If the list has multiple nodes, it moves the <code>head</code> to the <code>next</code> node to make it the new first node.</p>
</li>
<li><p>It points the new <code>head</code>’s <code>prev</code> to the <code>tail</code> to maintain the backward loop in the circular structure.</p>
</li>
<li><p>It points the <code>tail</code>’s <code>next</code> to the new <code>head</code> to keep the forward loop in the circular structure.</p>
</li>
<li><p>It clears the removed node’s <code>next</code> and <code>prev</code> pointers to disconnect it from the list.</p>
</li>
<li><p>It decreases the list’s length by one.</p>
</li>
<li><p>It returns the removed node’s data.</p>
</li>
</ul>
<p>This runs in O(1) time because you only change a few pointers without looping.</p>
<h3 id="heading-how-to-find-a-node-in-a-circular-doubly-linked-list">How to Find a Node in a Circular Doubly Linked List</h3>
<p>The goal is to find the node at a specific index in your circular doubly linked list.</p>
<p>Modify the <code>find</code> method in your <code>CircularDoublyLinkedList</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head || idx &lt; <span class="hljs-number">0</span> || idx &gt;= <span class="hljs-built_in">this</span>.len) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; idx; i++) {
    current = current!.next!;
  }

  <span class="hljs-keyword">return</span> current;
}
</code></pre>
<p>The <code>idx</code> prop is the position in the list. Here’s how <code>find</code> works:</p>
<ul>
<li><p>It checks if the list is empty or the index is invalid. If the <code>head</code> is <code>null</code>, <code>idx</code> is negative, or <code>idx</code> is too large, it returns <code>null</code> because no node exists.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> forward through the <code>next</code> pointers as many times as the index value.</p>
</li>
<li><p>Once you exit the loop, it returns the <code>current</code> node, which is at the specified index.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse up to <code>n</code> nodes to reach the index.</p>
<h3 id="heading-how-to-traverse-a-circular-doubly-linked-list">How to Traverse a Circular Doubly Linked List</h3>
<p>The goal is to return an array of all node data in your circular doubly linked list.</p>
<p>Modify the <code>traverse</code> method in your <code>CircularDoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

traverse(): T[] {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> [];

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
  <span class="hljs-keyword">const</span> result: T[] = [];

  <span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">if</span> (!current.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);

    result.push(current.data);

    current = current.next;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>Here’s how <code>traverse</code> works:</p>
<ul>
<li><p>If the list is empty, it returns an empty array.</p>
</li>
<li><p>It creates an empty array to store the node data.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It adds the <code>current</code> node’s data to the array.</p>
</li>
<li><p>It moves <code>current</code> to the next node using the <code>next</code> pointer.</p>
</li>
<li><p>It repeats adding data and moving <code>current</code> until you circle back to the <code>head</code>.</p>
</li>
<li><p>It returns the array with all node data.</p>
</li>
</ul>
<p>This runs in O(n) time because you need to visit every node in the list.</p>
<h3 id="heading-how-to-delete-a-node-from-a-circular-doubly-linked-list">How to Delete a Node from a Circular Doubly Linked List</h3>
<p>The goal is to remove the first node with the given value from your circular doubly linked list and return <code>true</code> if successful.</p>
<p>Modify the delete method in your <code>CircularDoublyLinkedList</code> class located in:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

<span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

  <span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">if</span> (current.data === data) {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
        <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
        <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
      } <span class="hljs-keyword">else</span> {
        current.prev!.next = current.next;
        current.next!.prev = current.prev;
        <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.head) {
          <span class="hljs-built_in">this</span>.head = current.next;
        }
        <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.tail) {
          <span class="hljs-built_in">this</span>.tail = current.prev;
        }
      }
      <span class="hljs-built_in">this</span>.len--;
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    current = current.next!;
  } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>The <code>data</code> prop is the value to find and remove. Here’s how <code>delete</code> works:</p>
<ul>
<li><p>If the list is empty, then it returns <code>false</code> because there’s nothing to delete.</p>
</li>
<li><p>It creates a new pointer called <code>current</code> at the <code>head</code>.</p>
</li>
<li><p>It moves <code>current</code> through the list and checks each node’s value until you circle back to the <code>head</code>.</p>
</li>
<li><p>If <code>current</code>’s value matches data, it checks if the list has one node, if so, it sets both <code>head</code> and <code>tail</code> to <code>null</code> since the single node within the list is both the <code>head</code> and the <code>tail</code>.</p>
</li>
<li><p>If the list has multiple nodes, it links the previous node’s <code>next</code> to the next node and the next node’s <code>prev</code> to the previous node to skip <code>current</code>.</p>
</li>
<li><p>If <code>current</code> is the <code>head</code>, it updates the <code>head</code> to the next node. If <code>current</code> is the <code>tail</code>, it updates the <code>tail</code> to the previous node.</p>
</li>
<li><p>It decreases the list’s length by one and returns <code>true</code>.</p>
</li>
<li><p>If no match, it moves <code>current</code> to the next node and continues checking.</p>
</li>
<li><p>If you circle back to the <code>head</code> without a match, it returns <code>false</code>.</p>
</li>
</ul>
<p>This runs in O(n) time because you may need to traverse the entire list to find the node.</p>
<h3 id="heading-how-to-insert-a-node-at-a-specific-position-in-a-circular-doubly-linked-list"><strong>How to Insert a Node at a Specific Position in a</strong> Circular Doubly Linked List</h3>
<p>The goal is to add a new node at a specific index in your circular doubly linked list.</p>
<p>Modify the <code>insertAt</code> method in your <code>CircularDoublyLinkedList</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt; <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">this</span>.prepend(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">if</span> (idx === <span class="hljs-built_in">this</span>.len) {
    <span class="hljs-built_in">this</span>.append(data);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
  <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.find(idx);

  <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  newNode.next = current;
  newNode.prev = current!.prev;
  current.prev!.next = newNode;
  current.prev = newNode;

  <span class="hljs-built_in">this</span>.len++;
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>The <code>idx</code> prop is the position in the list, and <code>data</code> is the value.</p>
<p>Here’s how <code>insertAt</code> works:</p>
<ul>
<li><p>If <code>idx</code> is negative or greater than the list’s length, then the <code>idx</code> prop is an invalid index, and you should return <code>false</code> to stop the operation.</p>
</li>
<li><p>If the index is 0, it calls <code>prepend</code> to add the node at the start and returns <code>true</code>.</p>
</li>
<li><p>If the <code>idx</code> equals the list's length, you are adding a new tail. In this case, it calls <code>append</code> to add the node at the end and returns true.</p>
</li>
<li><p>If the above conditions are not met, it creates a new node with the given data.</p>
</li>
<li><p>It finds the node at the given index using the <code>find</code> method and stores it as <code>current</code>.</p>
</li>
<li><p>If no node is found at the <code>idx</code>, it returns <code>false</code>.</p>
</li>
<li><p>It points the new node’s <code>next</code> to <code>current</code>. This sets the new node to precede <code>current</code> in the forward direction of the circular list.</p>
</li>
<li><p>This sets the new node’s <code>prev</code> to <code>current</code>’s <code>prev</code> node. This links the new node to the node before <code>current</code> and keeps the backward link in the circular list intact.</p>
</li>
<li><p>It sets the previous node's <code>next</code> to the new node, so the node before <code>current</code> now links to the new node. This keeps the circular loop intact by making sure the forward chain skips the original predecessor of <code>current</code> and includes the new node.</p>
</li>
<li><p>It sets <code>current</code>'s <code>prev</code> to the new node. This completes the insertion by making <code>current</code> link back to the new node and keeping the circular structure with correct two-way links.</p>
</li>
<li><p>It increases the list’s length by one.</p>
</li>
<li><p>It returns <code>true</code> to show the node was inserted.</p>
</li>
</ul>
<p>This runs in O(n) time because finding the index may require traversing the list.</p>
<h3 id="heading-how-to-test-your-circular-doubly-linked-list">How to Test Your Circular Doubly Linked List</h3>
<p>Great job! You’ve completed the circular doubly linked list, and now you’re ready to test your implementation.</p>
<p>Your final implementation should look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/circular-2.ts</span>

<span class="hljs-comment">/** Node for circular doubly linked list */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> N&lt;T&gt; {
  <span class="hljs-comment">/** Node data */</span>
  <span class="hljs-keyword">public</span> data;
  <span class="hljs-comment">/** Next node reference */</span>
  <span class="hljs-keyword">public</span> next: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Previous node reference */</span>
  <span class="hljs-keyword">public</span> prev: N&lt;T&gt; | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">/** Creates a node with given data */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">data: T</span>) {
    <span class="hljs-built_in">this</span>.data = data;
    <span class="hljs-built_in">this</span>.next = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.prev = <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-comment">/** Circular doubly linked list implementation */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularDoublyLinkedList&lt;T&gt; {
  <span class="hljs-comment">/** Head node */</span>
  <span class="hljs-keyword">public</span> head: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** Tail node */</span>
  <span class="hljs-keyword">public</span> tail: N&lt;T&gt; | <span class="hljs-literal">null</span>;
  <span class="hljs-comment">/** List length */</span>
  <span class="hljs-keyword">public</span> len: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/** Creates an empty list */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len = <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/** Adds node to list end */</span>
  append(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
    }

    <span class="hljs-built_in">this</span>.len++;
  }

  <span class="hljs-comment">/** Removes and returns tail node data */</span>
  deleteTail(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.tail) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.tail;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail.prev;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
    }

    removedItem.next = <span class="hljs-literal">null</span>;
    removedItem.prev = <span class="hljs-literal">null</span>;
    <span class="hljs-built_in">this</span>.len--;

    <span class="hljs-keyword">return</span> removedItem.data;
  }

  <span class="hljs-comment">/** Adds node to list start */</span>
  prepend(data: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);

    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head = newNode;
    }

    <span class="hljs-built_in">this</span>.len++;
  }

  <span class="hljs-comment">/** Removes and returns head node data */</span>
  deleteHead(): T | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">let</span> removedItem = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.head = removedItem.next;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
    }

    <span class="hljs-built_in">this</span>.len--;
    removedItem.next = <span class="hljs-literal">null</span>;
    removedItem.prev = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">return</span> removedItem.data;
  }

  <span class="hljs-comment">/** Finds node at given index */</span>
  find(idx: <span class="hljs-built_in">number</span>): N&lt;T&gt; | <span class="hljs-literal">null</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head || idx &lt; <span class="hljs-number">0</span> || idx &gt;= <span class="hljs-built_in">this</span>.len) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; idx; i++) {
      current = current!.next!;
    }

    <span class="hljs-keyword">return</span> current;
  }

  <span class="hljs-comment">/** Removes first node with given data */</span>
  <span class="hljs-keyword">delete</span>(data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;

    <span class="hljs-keyword">do</span> {
      <span class="hljs-keyword">if</span> (current.data === data) {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.len === <span class="hljs-number">1</span>) {
          <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
          <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
        } <span class="hljs-keyword">else</span> {
          current.prev!.next = current.next;
          current.next!.prev = current.prev;
          <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.head) {
            <span class="hljs-built_in">this</span>.head = current.next;
          }
          <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.tail) {
            <span class="hljs-built_in">this</span>.tail = current.prev;
          }
        }
        <span class="hljs-built_in">this</span>.len--;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }
      current = current.next!;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }

  <span class="hljs-comment">/** Returns array of node data */</span>
  traverse(): T[] {
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.head) <span class="hljs-keyword">return</span> [];

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.head;
    <span class="hljs-keyword">const</span> result: T[] = [];

    <span class="hljs-keyword">do</span> {
      <span class="hljs-keyword">if</span> (!current.next) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid list"</span>);

      result.push(current.data);

      current = current.next;
    } <span class="hljs-keyword">while</span> (current !== <span class="hljs-built_in">this</span>.head);

    <span class="hljs-keyword">return</span> result;
  }

  <span class="hljs-comment">/** Inserts node at given index */</span>
  insertAt(idx: <span class="hljs-built_in">number</span>, data: T): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">if</span> (idx &lt; <span class="hljs-number">0</span> || idx &gt; <span class="hljs-built_in">this</span>.len) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (idx === <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">this</span>.prepend(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">if</span> (idx === <span class="hljs-built_in">this</span>.len) {
      <span class="hljs-built_in">this</span>.append(data);
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">let</span> newNode = <span class="hljs-keyword">new</span> N(data);
    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.find(idx);

    <span class="hljs-keyword">if</span> (!current) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    newNode.next = current;
    newNode.prev = current!.prev;
    current.prev!.next = newNode;
    current.prev = newNode;

    <span class="hljs-built_in">this</span>.len++;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>Run the following command to test the linked list:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file circular-2
</code></pre>
<p>If the tests pass successfully, you’re all set! If any tests fail, review <code>src/examples/circular-2.ts</code>, fix the issues, and run the tests again.</p>
<h2 id="heading-when-to-use-linked-lists-and-when-to-avoid-them">When to Use Linked Lists (and When to Avoid Them)</h2>
<p>Linked lists are powerful data structures, but they're not always the best choice. So it's important to know when to use them and when to choose an alternative.</p>
<h3 id="heading-why-use-linked-lists">Why Use Linked Lists?</h3>
<p>Linked lists are great for situations that need dynamic data or flexible navigation.</p>
<p>Their main benefits include:</p>
<ul>
<li><p><strong>Dynamic size</strong>: Add or remove nodes without resizing, unlike arrays that need reallocation.</p>
</li>
<li><p><strong>Efficient insertions/deletions</strong>: Operations like <code>prepend</code> or <code>delete</code> are quick (<code>O(1)</code> at known positions), which is very ideal for frequent updates.</p>
</li>
<li><p><strong>Flexible traversal</strong>: Doubly and circular lists allow you to move forward or backward, which makes them helpful for complex navigation patterns.</p>
</li>
</ul>
<h3 id="heading-real-world-use-cases">Real-World Use Cases</h3>
<p>You should consider using linked lists in scenarios where the data is frequently updated or requires cyclic or bidirectional access:</p>
<ul>
<li><p><strong>Browser history</strong>: A doubly linked list keeps track of visited pages and lets users easily move back and forth. Adding a new page (<code>prepend</code>) or removing one (<code>delete</code>) is fast, and the list grows dynamically as users browse.</p>
</li>
<li><p><strong>Music playlists</strong>: Circular doubly linked lists are used for looping playlists in apps like Spotify. Users can easily skip forward (<code>next</code>) or backward (<code>prev</code>), and new songs (<code>append</code>) fit smoothly into the loop.</p>
</li>
<li><p><strong>Undo/redo functionality</strong>: Text editors use doubly linked lists to store actions. Each edit is a node, and moving backward (<code>undo</code>) or forward (<code>redo</code>) navigates through the list.</p>
</li>
<li><p><strong>Task scheduling</strong>: Circular singly linked lists are used for round-robin scheduling in operating systems. Each process is a node, and the list cycles through them to allocate CPU time. New tasks are added using <code>append</code>.</p>
</li>
</ul>
<h3 id="heading-when-not-to-use-linked-lists">When Not to Use Linked Lists</h3>
<p>Despite their strengths, linked lists have weaknesses in some situations because of their structure:</p>
<ul>
<li><p><strong>Slow random access</strong>: Reaching an index requires you to traverse from the head (<code>O(n)</code>), unlike arrays, which have <code>O(1)</code> access.</p>
</li>
<li><p><strong>High memory overhead</strong>: Each node in a linked list stores pointers (<code>next</code>, <code>prev</code>), which uses more memory than arrays. This can be an issue for large datasets.</p>
</li>
<li><p><strong>Poor search performance</strong>: Finding a value requires checking each node (<code>O(n)</code>), which is slower than hash tables (<code>O(1)</code>) or binary search trees (<code>O(log n)</code>).</p>
</li>
</ul>
<h3 id="heading-better-alternatives-for-specific-cases">Better Alternatives for Specific Cases</h3>
<p>In some cases, other data structures outperform linked lists:</p>
<ul>
<li><p><strong>Random access</strong>: Use arrays or dynamic arrays (like JavaScript’s <code>Array</code>) for quick indexing. For instance, if you need to show a table in a web app, an array's <code>O(1)</code> access lets you quickly reach any row.</p>
</li>
<li><p><strong>Frequent searches</strong>: Hash tables (like JavaScript’s <code>Map</code>) are better for fast lookups. For example, a contact list app that searches by name would use a hash table to speed up the process.</p>
</li>
<li><p><strong>Memory-constrained environments</strong>: Arrays use less memory for large, fixed-size datasets, such as image processing buffers in graphics apps.</p>
</li>
</ul>
<p>The key takeaway is that linked lists are great when your data needs dynamic growth, frequent insertions or deletions, or cyclic navigation, like in playlists or history features.</p>
<p>Avoid using linked lists for random access, frequent searches, or memory-sensitive tasks, where arrays, hash tables, or trees are better options.</p>
<p>You can experiment with your <code>src/playground</code> implementations to see how linked lists fit your project’s needs.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations on finishing this handbook! 🥳 You've learned how to implement different types of linked lists using TypeScript, including singly linked lists, doubly linked lists, and circular linked lists.</p>
<p>By understanding these linked lists, you're well-prepared to work with more complex data structures.</p>
<p>Thanks for following along with this tutorial. You can follow me on <a target="_blank" href="https://x.com/Yazdun">X</a>, where I share more useful tips on data structures and web development.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
