<?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[ #linkedlists - 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[ #linkedlists - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 26 May 2026 04:43:58 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/linkedlists/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <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="2160" height="832" 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="2898" height="1118" 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="1702" height="834" 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="2566" height="1244" 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>
