This is the second part of a series about Data Structures in JS. The following list resumes all parts:

Like in the previous article I will start explaining the base of this structure. That is the nodes. In this case, the Double Linked Nodes.

A Node has three data elements:

Value : The value that the node stores. Using a type-less language that JS or templates in other like C++ allows this element to be any type.

: The value that the node stores. Using a type-less language that JS or templates in other like C++ allows this element to be any type. Previous : The previous element in the list.

: The previous element in the list. Next: The next element in the list.

Double Linked Node

Pretty easy, right? Let’s go with the list itself.

class DLList { constructor(values) { this.header = new DLListNode(null, null, null); this.tail = new DLListNode(this.header, null, null); this.header.setNext(this.tail); this.elements = 0; } // Cost: O(1) erase(pos) { if (pos.assertIsValid()) { let curr = pos.current(); const prev = curr.getPrev(); const next = curr.getNext(); prev.setNext(next); next.setPrev(prev); curr = null; this.elements--; return DLListIterator[Symbol.iterator](next, this); } } // Cost: O(1) insert(pos, val) { const endVal = this.end().current(); if ( (pos.assertIsValid() || pos.current() === endVal) && this.find(val).current() === endVal ) { const curr = pos.current(); const prev = curr.getPrev(); const newNode = new DLListNode(prev, val, curr); prev.setNext(newNode); curr.setPrev(newNode); this.elements++; return DLListIterator[Symbol.iterator](newNode, this); } return DLListIterator[Symbol.iterator](null, this); } // Cost: O(n) find(item) { const iterator = this.begin(); while (iterator.current() !== this.end().current()) { if (iterator.current() !== null && iterator.current().getValue() === item) break; iterator.next(); } return iterator; } // Cost: O(1) end() { return DLListIterator[Symbol.iterator](this.tail, this); } ... more methods

}

This is the link to the Github repo with all the working code of the App.

A Doubly Linked List is a class that aglomerates the linked nodes that forms itself. It doesn’t allow repeated values and as you can see, the list has the following elements:

Header : Is the first node of the list, the entry point for the iterator.

: Is the first node of the list, the entry point for the iterator. Tail : A node like the Header but in the other side. It helps to have some common methods like end() with a constant complexity.

: A node like the Header but in the other side. It helps to have some common methods like end() with a constant complexity. Elements: A simple counter to make a fast and cheap check about the current elements in the list.

Header and Tail are not counted like normal nodes as they are not erasables.

Despite in single nodes, in double we can get the previous with a constant complexity, so Insert, Erase and End methods have also an O(1) complexity. In this structure the only methods that still have an O(n) complexity are find and clear. Let’s make an small comparision:

The most common base methods (insert and erase) are now with a constant complexity at the cost of add a reference of the previous in each node. Worths it! Now comes the only part that really matters:

When and how to use Double Linked Lists?

As pointed before, this lists doesn’t allow repeated elements, so this is the first restriction you have. Arrays are tipically the first structure that you think about when looking for store data. Lists give you much more functionality at a cheaper cost. In my opinion most JS developers discard (or ignore) other data structure.

This lists I developed are the base to build better lists that fit your project. For example, if you are working with a relational databases that tipically have an unique id, you can transform the value of this lists to turn it into a key value pair, respecting the “unique” restriction of this lists. This is the tipical case when you should use lists instead arrays because the methods of the base class have a complexity of O(1) instead O(n).

In a web page with a front logic that manges something like 1000 elements you will not see the difference. However, with millions of records, you should take care about the best data structure and strategy to manage with your data.

You can test the React App here:

And the Github Repo with all this code:

Reach me on twitter (@Oliver_ap)