<?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" version="2.0"><channel><title><![CDATA[StackFull.dev: just dev stuffs]]></title><description><![CDATA[A collection of articles on algorithms, software development and system design. Also contains occasional dev rants.]]></description><link>https://stackfull.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1630042058135/4fMW2DA4x.png</url><title>StackFull.dev: just dev stuffs</title><link>https://stackfull.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 06:26:13 GMT</lastBuildDate><atom:link href="https://stackfull.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Implementing virtual scroll for web from scratch, in less than 150 lines of code]]></title><description><![CDATA[What is virtual scroll ?
Virtual scroll (also called virtualization or windowing) is a technique used to efficiently render large lists in web applications — without loading everything into the DOM at once. Instead of rendering 1,000+ items, you only...]]></description><link>https://stackfull.dev/implementing-virtual-scroll-for-web-from-scratch-in-less-than-150-lines-of-code</link><guid isPermaLink="true">https://stackfull.dev/implementing-virtual-scroll-for-web-from-scratch-in-less-than-150-lines-of-code</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[scroll]]></category><category><![CDATA[performance]]></category><category><![CDATA[virtualization]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sun, 13 Apr 2025 08:31:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/aXeVH4FcS1k/upload/e4bb42daae4863989e80e62edace6f90.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-virtual-scroll">What is virtual scroll ?</h2>
<p><strong>Virtual scroll</strong> (also called <strong>virtualization</strong> or <strong>windowing</strong>) is a technique used to efficiently render large lists in web applications — <strong>without loading everything into the DOM at once</strong>. Instead of rendering <strong>1,000+ items</strong>, you only render what's <strong>visible in the viewport</strong>, plus a small buffer above and below for smooth scrolling.</p>
<p>As you scroll, items outside the viewport are removed from the DOM, and new ones are added on-demand. Let’s see how we would implement it from scratch. We’ll would use ReactJS to create a reusable component in this post, but these principles can be applied to any framework or even vanilla JS.</p>
<h2 id="heading-step-1-prepare-data-for-scroll">Step 1: prepare data for scroll</h2>
<p>First off, let’s get the preparatory step out of the way. It’s not directly related to the idea of virtual scroll, but we’ll need it done to test our implementation later. Here’s a simple snippet that we can use to generate a huge list with random data:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> ARR_SIZE = <span class="hljs-number">500</span>_000;

<span class="hljs-keyword">const</span> arr = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(ARR_SIZE).fill(<span class="hljs-literal">null</span>).map(<span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> ({
  <span class="hljs-attr">index</span>: i + <span class="hljs-number">1</span>,
  <span class="hljs-attr">id</span>: <span class="hljs-built_in">Math</span>.random(),
  <span class="hljs-attr">value</span>: <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">2</span> * ARR_SIZE),
}));
</code></pre>
<p>We’ll create an array with <strong>500,000</strong> fake rows. Each one having:</p>
<ul>
<li><p>an index (like 1, 2, 3…)</p>
</li>
<li><p>a random ID</p>
</li>
<li><p>a random value (just to show data)</p>
</li>
</ul>
<h2 id="heading-step-2-the-core-idea">Step 2: the core idea</h2>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*814PZGqmFkIxq-_UNNY6QA.png" alt="Reverse Infinite Scroll in react using TanStack Virtual | by Rahul  Moghariya | Medium" /></p>
<p>The core idea can be understood by the diagram above.</p>
<p>We provide a fixed size container to the user, to scroll things within it. Let’s call that <code>windowHeight</code>. Each row/item is also given a fixed size, say <code>rowHeight</code>. This means we can have atmost <code>windowHeight/rowHight</code> items shown in the container, let’s call that <code>WINDOW_SIZE</code>.</p>
<p>As the user starts scrolling the container, we keep track of the height that has scrolled up (<code>container.scrollTop</code> value). We can use this value along with <code>rowHeight</code> to calculate the index at which container should start showing the items. Similarly, we can use <code>windowHeight</code> to calculate the index at which container should stop showing the items.</p>
<p>As the user keeps scrolling, we keep recalculating the start and end index for the items to be shown and re-render those in the UI.</p>
<p>An interesting thing to note here is the scroll position. Simply rendering the items from start to end index would reset the scroll position, thus not allowing the user to scroll anymore, so we need some way for maintaining desired scroll position. A simple way to achieve this would be to slap two <code>divs</code>, one at top of the container and another at bottom, each having height equal to expected scroll offsets at top and bottom. We’ll see how to implement this shortly.</p>
<p>This pretty much is the crux of the solution. Let’s get our hands dirty with some code now.</p>
<h2 id="heading-step-3-basic-implementation">Step 3 - basic implementation</h2>
<p>Lets create a component <code>VirtualTable</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// windowSize is the number of rows to be shown in the window.</span>
<span class="hljs-comment">// rowHeight is the fixed height of each row.</span>
<span class="hljs-comment">// arr contains the huge data to be shown in virtualTable.</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">VirtualTable</span>(<span class="hljs-params">{ arr, windowSize, rowHeight }</span>) </span>{
    ...
}
</code></pre>
<p>Let’s track the scroll position as we talked earlier:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [scrollTop, setScrollTop] = useState(<span class="hljs-number">0</span>);

<span class="hljs-keyword">const</span> handleScroll = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  e.preventDefault();
  setScrollTop(e.target.scrollTop);
};

...
return (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">onScroll</span>=<span class="hljs-string">{handleScroll}</span> <span class="hljs-attr">...</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>Now let’s calculate the start and index for items to be shown within the virtual table:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> startIndex = <span class="hljs-built_in">Math</span>.floor(scrollTop / rowHeight);


<span class="hljs-comment">// Better, let's clamp it to 0, to ensure it never becomes negative.</span>
<span class="hljs-keyword">const</span> startIndex = <span class="hljs-built_in">Math</span>.max(<span class="hljs-number">0</span>, <span class="hljs-built_in">Math</span>.floor(scrollTop / rowHeight));

<span class="hljs-comment">// Similar calculation for endIndex:</span>
<span class="hljs-keyword">const</span> endIndex = <span class="hljs-built_in">Math</span>.min(arr.length - <span class="hljs-number">1</span>, startIndex + windowSize - <span class="hljs-number">1</span>);
</code></pre>
<p>Maintain list of items to be rendered:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> shownRowsIndex = [];

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = startIndex; i &lt;= endIndex; i++) {
  shownRowsIndex.push(i);
}
</code></pre>
<p>We want the scroll bar to feel like it scrolls through the <strong>whole</strong> list, even though we’re only rendering a few items. So we fake the total height using invisible <code>div</code>s.</p>
<p>Padding above:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> topPad = startIndex * rowHeight;
</code></pre>
<p>This means: if you’ve scrolled past 20 items, we add 20 × row height = 600px of empty space at the top.</p>
<p>Padding below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> bottomPad = totalHeight - (renderedHeight + topPad);
</code></pre>
<p>This calculates how much space is left <strong>after</strong> the visible rows.</p>
<p>So if total height is 15,000px, and you’ve shown 30 rows and scrolled past 600px, we add just enough padding to fill in the rest.</p>
<p>Rendered output looks like this:</p>
<pre><code class="lang-javascript">&lt;div
  onScroll={handleScroll}
    style={{
    <span class="hljs-attr">height</span>: rowHeight * windowSize,
    <span class="hljs-attr">overflowY</span>: <span class="hljs-string">'auto'</span>,
  }}
&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> <span class="hljs-attr">topPad</span> }}&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

  {shownRowsIndex.map(<span class="hljs-function">(<span class="hljs-params">itemIndex</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">"t-row"</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> <span class="hljs-attr">rowHeight</span> }}
      <span class="hljs-attr">key</span>=<span class="hljs-string">{arr[itemIndex].id}</span>
    &gt;</span>
      row#{arr[itemIndex].index} : {arr[itemIndex].value}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  ))}

  &lt;div style={{ <span class="hljs-attr">height</span>: bottomPad }}&gt;&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>You can see it all in action in <a target="_blank" href="https://jspad.dev/?id=4GHi0vdXSjaltkjcxORr&amp;o=2&amp;c=2">JSPad</a>:</p>
<p><a target="_blank" href="https://jspad.dev/?id=4GHi0vdXSjaltkjcxORr&amp;o=1&amp;c=2"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744530427001/45f6af83-2636-4e0a-8e67-f09faa5e862f.png" alt class="image--center mx-auto" /></a></p>
<h2 id="heading-step-4-optimizations">Step 4 - Optimizations</h2>
<p>So far, we’ve covered the basics of virtual scroll: Only render what’s visible.<br />But once that works, you start to notice two issues:</p>
<ol>
<li><p>Scrolling can feel a little “jumpy”.</p>
</li>
<li><p>Updating on every pixel of scroll becomes expensive.</p>
</li>
</ol>
<p>Let’s fix both — starting with <strong>buffering</strong>.</p>
<hr />
<h3 id="heading-1-buffer-rows-why-they-matter">1. Buffer Rows — Why They Matter</h3>
<p>Without buffer, when you scroll down, new rows <strong>only</strong> appear when they come <strong>exactly</strong> into view. This causes a harsh snapping effect — rows are constantly entering and exiting the DOM too quickly.</p>
<p>With buffer, we render a few extra rows <strong>above and below</strong> the viewport. So even if a row is <em>just offscreen</em>, it’s already in the DOM and ready to slide in. This makes scrolling feel buttery smooth.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> SCROLL_BUFFER_SIZE = <span class="hljs-built_in">Math</span>.floor(WINDOW_SIZE / <span class="hljs-number">2</span>);
...
const startIndex = <span class="hljs-built_in">Math</span>.floor(
  (scrollTop - bufferSize * rowHeight) / rowHeight
);

<span class="hljs-keyword">const</span> endIndex = startIndex + <span class="hljs-number">2</span> * bufferSize + windowSize - <span class="hljs-number">1</span>;
</code></pre>
<p>This adds <strong>half the container size worth</strong> of rows above and below.</p>
<p>So if you're supposed to show rows 50–65, you might actually render 43–72, and visually clip the rest.</p>
<hr />
<h3 id="heading-2-throttling-why-we-need-it">2. Throttling — Why We Need It</h3>
<p>React re-renders <strong>every time scrollTop changes</strong>. And when you scroll rapidly, <code>onScroll</code> can fire <strong>dozens of times per second</strong>. That’s... too much.</p>
<p>Without control, this leads to:</p>
<ul>
<li><p>Too many state updates</p>
</li>
<li><p>Laggy performance</p>
</li>
<li><p>Unnecessary DOM churn</p>
</li>
</ul>
<p><strong>Solution: Throttle scroll updates-</strong> We write a small helper:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">throttle</span>(<span class="hljs-params">fn, t</span>) </span>{
  <span class="hljs-keyword">let</span> blocked;
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">...args</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (blocked) <span class="hljs-keyword">return</span>;
    blocked = <span class="hljs-literal">true</span>;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> (blocked = <span class="hljs-literal">false</span>), t);
    <span class="hljs-keyword">return</span> fn.apply(<span class="hljs-built_in">this</span>, args);
  };
}
</code></pre>
<p>This allows us to call <code>setScrollTop()</code> at most <strong>once every 100ms</strong>. In the component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> throttledScroll = throttle(handleScroll, <span class="hljs-number">100</span>);

...
&lt;div onScroll={throttleScroll}&gt; ... &lt;/div&gt;
</code></pre>
<p>This way, even during fast scrolling, React doesn’t panic trying to keep up.</p>
<h2 id="heading-step-5-putting-it-all-together-to-test">Step 5: Putting it all together to test</h2>
<p>You can find the final result and play around with the implementation yourself in <a target="_blank" href="https://jspad.dev/?o=1&amp;id=tz8HaZh9p25vygxKPAPl&amp;c=2">JSPad</a>:</p>
<p><a target="_blank" href="https://jspad.dev/?o=1&amp;id=tz8HaZh9p25vygxKPAPl&amp;c=2"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744530904905/e171e506-7208-423a-82bb-5ec2eb1f3032.png" alt class="image--center mx-auto" /></a></p>
<p>This isn’t all though. We can still make this more generic and performant, there’s still ample scope for tweaks and improvements. For example, how do we account for rows with different heights?</p>
<p>I’ll leave this question open for now, and maybe address it in a future post!</p>
<p>Cheers until then!</p>
]]></content:encoded></item><item><title><![CDATA[Graph data structure in Typescript]]></title><description><![CDATA[The graph data structure is a fundamental concept in computer science, and it is used in various domains such as social networks, transportation systems, and computer networks.
A graph is a collection of nodes connected by edges, where each node repr...]]></description><link>https://stackfull.dev/graph-data-structure-in-typescript</link><guid isPermaLink="true">https://stackfull.dev/graph-data-structure-in-typescript</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[graphs]]></category><category><![CDATA[datastructure]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sun, 23 Apr 2023 06:42:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/2IVaDuuD2QU/upload/0acb30aeab9920453642b15e33e4b70b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The graph data structure is a fundamental concept in computer science, and it is used in various domains such as social networks, transportation systems, and computer networks.</p>
<p>A graph is a <strong>collection of nodes connected by edges</strong>, where each node represents an entity, and each edge represents a relationship between two entities. In this article, we will discuss how to implement a graph data structure in TypeScript and perform BFS and DFS on it.</p>
<h3 id="heading-implementing-graph-data-structure-in-typescript">Implementing Graph Data Structure in TypeScript</h3>
<p>In TypeScript, we can implement a graph data structure using classes. We will define two classes, namely Node and Graph, to represent a node and a graph, respectively.</p>
<p>The Node class will have two properties: value and neighbors:</p>
<ul>
<li><p><code>value</code> property will hold the value of the node.</p>
</li>
<li><p><code>neighbors</code> property will hold an array of neighboring nodes.</p>
</li>
</ul>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Node {
  value: <span class="hljs-built_in">any</span>;
  neighbors: Node[];

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

  addNeighbor(node: Node) {
    <span class="hljs-built_in">this</span>.neighbors.push(node);
  }
}
</code></pre>
<p>The Graph class will have one property, <code>nodes</code>, which will hold an array of all the nodes in the graph. It will also have two methods, <code>addNode</code> and <code>addEdge</code>, to add a node and an edge to the graph, respectively.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Graph {
  nodes: Node[];

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-built_in">this</span>.nodes = [];
  }

  addNode(value: <span class="hljs-built_in">any</span>) {
    <span class="hljs-keyword">const</span> node = <span class="hljs-keyword">new</span> Node(value);
    <span class="hljs-built_in">this</span>.nodes.push(node);
  }

  addEdge(source: Node, destination: Node) {
    source.addNeighbor(destination);
    destination.addNeighbor(source);
  }
}
</code></pre>
<h3 id="heading-graph-traversal-breadth-first-search-bfs">Graph traversal: Breadth-First Search (BFS)</h3>
<p>Breadth-First Search (BFS) is a graph traversal algorithm that visits all the nodes of a graph in breadth-first order, i.e., it visits all the nodes at the same level before moving to the next level. To perform BFS, we need to maintain a queue of nodes to be visited.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bfs</span>(<span class="hljs-params">startNode: Node</span>) </span>{
  <span class="hljs-keyword">const</span> visited: <span class="hljs-built_in">Set</span>&lt;Node&gt; = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>();
  <span class="hljs-keyword">const</span> queue: Node[] = [];

  visited.add(startNode);
  queue.push(startNode);

  <span class="hljs-keyword">while</span> (queue.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">const</span> currentNode = queue.shift()!;
    <span class="hljs-built_in">console</span>.log(currentNode.value);

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> neighbor <span class="hljs-keyword">of</span> currentNode.neighbors) {
      <span class="hljs-keyword">if</span> (!visited.has(neighbor)) {
        visited.add(neighbor);
        queue.push(neighbor);
      }
    }
  }
}
</code></pre>
<p>In the above code, we first initialize a set called visited to keep track of the nodes that have been visited. We also initialize a queue to hold the nodes to be visited. We add the <code>startNode</code> to both visited and queue. Then, while the queue is not empty, we dequeue the currentNode, print its value, and add its unvisited <code>neighbors</code> to the queue and visited set.</p>
<p>Here's a visual cue for the code above:</p>
<p><img src="https://www.codesdope.com/staticroot/images/algorithm/bfs8.png" alt="Breadth First Search (BFS) in Graphs" /></p>
<h3 id="heading-graph-traversal-depth-first-search-dfs">Graph-traversal: Depth-First Search (DFS)</h3>
<p>Depth-First Search (DFS) is a graph traversal algorithm that visits all the nodes of a graph in depth-first order, i.e., it visits all the nodes in a branch before moving to the next branch. To perform DFS, we need to maintain a stack of nodes to be visited.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dfs</span>(<span class="hljs-params">startNode: Node</span>) </span>{
  <span class="hljs-keyword">const</span> visited: <span class="hljs-built_in">Set</span>&lt;Node&gt; = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>();
  <span class="hljs-keyword">const</span> stack: Node[] = [];

  stack.push(startNode);

  <span class="hljs-keyword">while</span> (stack.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">const</span> currentNode = stack.pop()!;
    <span class="hljs-keyword">if</span> (!visited.has(currentNode)) {
      <span class="hljs-built_in">console</span>.log(currentNode.value);
      visited.add(currentNode);

      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> neighbor <span class="hljs-keyword">of</span> currentNode.neighbors) {
        stack.push(neighbor);
      }
    }
  }
}
</code></pre>
<p>We first initialize a set called visited to keep track of the nodes that have been visited. We also initialize a stack to hold the nodes to be visited. We push the <code>startNode</code> to the stack. Then, while the stack is not empty, we pop the currentNode from the stack, print its value, add it to the visited set, and push its unvisited <code>neighbors</code> to the stack.</p>
<p>Here's a visual cue:</p>
<p><img src="https://www.codesdope.com/staticroot/images/algorithm/dfs.gif" alt="animation of dfs" /></p>
<h3 id="heading-let-see-all-of-it-in-action">Let' see all of it in action</h3>
<p>Consider the following problem:</p>
<pre><code class="lang-markdown">Given a graph, find the shortest path between two nodes using BFS.
</code></pre>
<p>To solve this problem, we can use the BFS algorithm provided in this article. We start by adding the start node to the visited set and queue. Then, while the queue is not empty, we dequeue the <code>currentNode</code>, check if it is the target node, and return the path if it is. Otherwise, we add its unvisited <code>neighbors</code> to the queue and visited set, and update the path.</p>
<p>Here's the typescript code to solve the problem above:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">shortestPath</span>(<span class="hljs-params">graph: Graph, start: Node, target: Node</span>) </span>{
  <span class="hljs-keyword">const</span> visited: <span class="hljs-built_in">Set</span>&lt;Node&gt; = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>();
  <span class="hljs-keyword">const</span> queue: [Node, Node[]][] = [];

  queue.push([start, [start]]);

  <span class="hljs-keyword">while</span> (queue.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">const</span> [currentNode, currentPath] = queue.shift()!;

    <span class="hljs-keyword">if</span> (currentNode === target) {
      <span class="hljs-keyword">return</span> currentPath;
    }

    visited.add(currentNode);

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> neighbor <span class="hljs-keyword">of</span> currentNode.neighbors) {
      <span class="hljs-keyword">if</span> (!visited.has(neighbor)) {
        queue.push([neighbor, [...currentPath, neighbor]]);
      }
    }
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Heaps in JavaScript]]></title><description><![CDATA[So far we've looked at implementation of tree data structure and some of it's variants such as trie. In this post, we'll dive into heaps. These are also referred to as priority queues.
Introduction
Heap is a variant of tree data structure, with two a...]]></description><link>https://stackfull.dev/heaps-in-javascript</link><guid isPermaLink="true">https://stackfull.dev/heaps-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[data structures]]></category><category><![CDATA[interview]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Mon, 01 Nov 2021 13:43:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635774113570/9LP192gic.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So far we've looked at implementation of tree data structure and some of it's variants such as trie. In this post, we'll dive into heaps. These are also referred to as priority queues.</p>
<h1 id="heading-introduction">Introduction</h1>
<p>Heap is a variant of tree data structure, with two additional properties:</p>
<ol>
<li><strong>It is a Complete Binary Tree:</strong> Each level of a Complete Binary Tree contains the maximum number of nodes, <strong>except</strong> possibly the last layer, which must be filled from left to right. A <em>Complete Binary Tree is always balanced</em> by it's definition. For reference, the diagrams below show you when a tree can be called a CBT:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635684966623/fJ-3sFBXp.png" alt="Screen Shot 2021-10-31 at 6.25.59 PM.png" /></p>
<ol start="2">
<li><strong>Every node satisfies the "heap property":</strong> Heap property essentially means that for any given node C, if P is a parent node of C, then:</li>
</ol>
<ul>
<li><p>For a max heap: the key of P should be greater than or equal to the key of C.</p>
</li>
<li><p>For a min heap: the key of P should be less than or equal to the key of C.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635685306044/5sFKHAcSi.png" alt="Screen Shot 2021-10-31 at 6.31.38 PM.png" /></p>
</li>
</ul>
<h1 id="heading-how-to-represent-a-heap">How to represent a heap?</h1>
<p>If you've gone through the previous posts, you'd notice we usually start implementation with class representation of a node and then tie it up with class representation of the actual data structure itself. We can do the same for heaps as well. However, there's a simpler way of solving this problem, which is because of the one of the two properties that all heaps must abide by:</p>
<blockquote>
<p>All heaps must be Complete Binary Trees</p>
</blockquote>
<p>Since all heaps must be Complete Binary Trees and we know that all levels, excepts last one, in Complete Binary Tree must be completely filled. Also, for the last level, all children must be filled from left to right direction, without any gaps. This definition ensures that <strong>a Complete Binary Tree of n nodes can only have 1 possible shape</strong>. It, in turn, would allow us to represent the Complete Binary tree using an array. Which means, heaps can be represented using arrays too. For example, we can represent a simple heap as an array, as illustrated below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635754993627/MW9E2Q0iz.png" alt="Screen Shot 2021-11-01 at 1.53.07 PM.png" /></p>
<p>Key thing to note here is the relationship between parent and children nodes. If you look closely at the diagram above, we can deduce following:</p>
<ol>
<li><p>If a node is placed at index i in array, then given that the resultant index lies within length of the array:</p>
<ul>
<li><p>It's left child would be at (2i+1)th position</p>
</li>
<li><p>Right one would be at (2i+2)the position</p>
</li>
</ul>
</li>
<li><p>If a node is placed at index i in array, it's parent node would be located at <code>floor((i-1)/2)</code>th index.</p>
</li>
</ol>
<p>Diagram below makes it easier to consume the info above:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635755427268/GIWwdou92B.png" alt="Screen Shot 2021-11-01 at 2.00.18 PM.png" /></p>
<h1 id="heading-preparing-the-interface">Preparing the interface</h1>
<blockquote>
<p>Note: throughout the implementation we'll only be talking about min-heap. We'll later see that how the same idea can be easily extended to max-heap as well.</p>
</blockquote>
<p>Now that we've covered the representation details, let's come up with an interface for using the data structure. There are three key things we want to be able to achieve with the help of our heap data structure:</p>
<ol>
<li><p>Add a new key into the heap</p>
</li>
<li><p>Remove the max or min key from the heap (depending on whether it's min heap or max heap)</p>
</li>
<li><p>Get the max of min key from the heap (depending on whether it's min or max heap)</p>
</li>
</ol>
<p>Third operation is quite trivial. We know for the min heap, first item in the array would be the min key and similarly for max heap, first item in the array would max key. So we're left with implementation of two operations:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// adds the provided newKey into the min-heap named "heap"</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heappush</span>(<span class="hljs-params">heap, newKey</span>)</span>{}

<span class="hljs-comment">// removes the smallest key from the min-heap named "heap"</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heappop</span>(<span class="hljs-params">heap</span>)</span>{}
</code></pre>
<h1 id="heading-implementing-heappush">Implementing <code>heappush()</code></h1>
<p>How can we add a new key into the heap? Let's say we start by pushing the new key into the array. Pushing the new key still let's us abide by the first requirement of the heap i.e it must be a Complete Binary Tree. However, we need to ensure that it abides by the "heap property" as well.</p>
<p>We can do so by comparing the pushed item with it's parent. If parent is larger than the pushed item then we know heap property is being violated, hence we can swap. We can continue doing this swapping until a legal parent is found or we've reached top of the heap. Here's a visual guide for better reference:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635756963290/eWlfgF5JG.png" alt="Screen Shot 2021-11-01 at 2.25.57 PM.png" /></p>
<p>Here's the final implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heappush</span>(<span class="hljs-params">heap, newKey</span>)</span>{
  <span class="hljs-comment">// push the new key </span>
  heap.push(newKey);

  <span class="hljs-comment">// get the current index of pushed key</span>
  <span class="hljs-keyword">let</span> curr = heap.length<span class="hljs-number">-1</span>;

 <span class="hljs-comment">// keep comparing till root is reached or we terminate in middle</span>
  <span class="hljs-keyword">while</span>(curr &gt; <span class="hljs-number">0</span>){
    <span class="hljs-keyword">let</span> parent = <span class="hljs-built_in">Math</span>.floor((curr<span class="hljs-number">-1</span>)/<span class="hljs-number">2</span>)
    <span class="hljs-keyword">if</span>( heap[curr] &lt; heap[parent] ){
      <span class="hljs-comment">// quick swap</span>
      [ heap[curr], heap[parent] ] = [ heap[parent], heap[curr] ]
      <span class="hljs-comment">// update the index of newKey</span>
      curr = parent
    } <span class="hljs-keyword">else</span>{
      <span class="hljs-comment">// if no swap, break, since we heap is stable now</span>
      <span class="hljs-keyword">break</span>
    }
  } 
}
</code></pre>
<h1 id="heading-implementing-heappop">Implementing <code>heappop()</code></h1>
<p>Using <code>heappop()</code> we need to remove the topmost item of the heap. Meaning, for a min-heap the minimum key would be removed and for a max-heap maximum key would be removed. From the perspective of array, it simply means we should remove the first item of the array. But then which node should become the root ? If we randomly choose either of left or right children of the removed node, as new root node, that wouldn't guarantee following the heap property. We can follow these steps instead (for a min-heap):</p>
<ol>
<li><p>Swap the root node with last node (first item with last item in the array)</p>
</li>
<li><p>Remove the root node by popping the last item out of the array</p>
</li>
<li><p>Compare the new root node's key with it's children:</p>
<ul>
<li><p>If key is less than both of it's children keys then heap is stable</p>
</li>
<li><p>Else, swap the key with the smaller child key</p>
</li>
</ul>
</li>
<li><p>Repeat step 3 until last child is reached or the heap property is established.</p>
</li>
</ol>
<p>Essentially we're following a similar process as <code>heappush()</code>, except we're trying to establish the heap-property in <strong>top to bottom</strong> fashion i.e. start with the root and keep going till last child. In <code>heappush()</code> we followed opposite order i.e. start from the last child and keep going till the root.</p>
<p>Here's how the actual implementation looks like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heappop</span>(<span class="hljs-params">heap</span>)</span>{
 <span class="hljs-keyword">if</span> (heap.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
  <span class="hljs-comment">// swap root with last node</span>
  <span class="hljs-keyword">const</span> n = heap.length;
  [heap[<span class="hljs-number">0</span>], heap[n<span class="hljs-number">-1</span>]] = [ heap[n<span class="hljs-number">-1</span>], heap[<span class="hljs-number">0</span>]]

  <span class="hljs-comment">// remove the root i.e. the last item (because of swap)</span>
  <span class="hljs-keyword">const</span> removedKey = heap.pop();

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

  <span class="hljs-comment">// keep going till atleast left child is possible for current node</span>
  <span class="hljs-keyword">while</span>(<span class="hljs-number">2</span>*curr + <span class="hljs-number">1</span> &lt; heap.length){
    <span class="hljs-keyword">const</span> leftIndex = <span class="hljs-number">2</span>*curr+<span class="hljs-number">1</span>; 
    <span class="hljs-keyword">const</span> rightIndex = <span class="hljs-number">2</span>*curr+<span class="hljs-number">2</span>;
    <span class="hljs-keyword">const</span> minChildIndex = (rightIndex &lt; heap.length &amp;&amp; heap[rightIndex] &lt; heap[leftIndex] ) ? rightIndex :leftIndex;
    <span class="hljs-keyword">if</span>(heap[minChildIndex] &lt; heap[curr]){
     <span class="hljs-comment">// quick swap, if smaller of two children is smaller than the parent (min-heap)</span>
      [heap[minChildIndex], heap[curr]] = [heap[curr], heap[minChildIndex]]
      curr = minChildIndex
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">break</span>
    }
  }

  <span class="hljs-comment">// finally return the removed key</span>
  <span class="hljs-keyword">return</span> removedKey;
}
</code></pre>
<p>We can move the logic of maintaining heap property to seperate function for readability:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heappop</span>(<span class="hljs-params">heap</span>) </span>{
  <span class="hljs-keyword">if</span> (heap.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;

  <span class="hljs-keyword">const</span> n = heap.length;
  [heap[<span class="hljs-number">0</span>], heap[n - <span class="hljs-number">1</span>]] = [heap[n - <span class="hljs-number">1</span>], heap[<span class="hljs-number">0</span>]]; <span class="hljs-comment">// Swap root with last</span>
  <span class="hljs-keyword">const</span> min = heap.pop();                          <span class="hljs-comment">// Remove the real root</span>
  percolateDown(heap, <span class="hljs-number">0</span>);                          <span class="hljs-comment">// Restore heap property</span>

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


<span class="hljs-comment">// Maintains the heap property while moving the item downwards.</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">percolateDown</span>(<span class="hljs-params">heap, index</span>) </span>{
  <span class="hljs-keyword">let</span> curr = index;
  <span class="hljs-keyword">while</span> (<span class="hljs-number">2</span> * curr + <span class="hljs-number">1</span> &lt; heap.length) {
    <span class="hljs-keyword">const</span> leftIndex = <span class="hljs-number">2</span> * curr + <span class="hljs-number">1</span>;
    <span class="hljs-keyword">const</span> rightIndex = <span class="hljs-number">2</span> * curr + <span class="hljs-number">2</span>;
    <span class="hljs-keyword">const</span> minChildIndex =
      rightIndex &lt; heap.length &amp;&amp; heap[rightIndex] &lt; heap[leftIndex] ? rightIndex : leftIndex;
    <span class="hljs-keyword">if</span> (heap[minChildIndex] &lt; heap[curr]) {
      <span class="hljs-comment">// quick swap, if smaller of two children is smaller than the parent (min-heap)</span>
      [heap[minChildIndex], heap[curr]] = [heap[curr], heap[minChildIndex]];
      curr = minChildIndex;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">break</span>;
    }
  }
}
</code></pre>
<h1 id="heading-creating-a-heap-using-an-exisiting-array">Creating a heap using an exisiting array</h1>
<p>Creating a heap from a pre-existing array looks pretty simple. Just create an empty heap and then iterate through all items of the array and perform <code>heappush()</code>:</p>
<pre><code class="lang-javascript">
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heapify</span>(<span class="hljs-params">arr</span>)</span>{
  <span class="hljs-keyword">const</span> heap = []
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> item <span class="hljs-keyword">of</span> arr){
     heappush(heap, item)
  }
  <span class="hljs-keyword">return</span> heap;
}
</code></pre>
<p>But can we do slightly better here? Yes. First off, we can avoid using extra space for the new heap altogether. Why not just re-arrange the items of the array itself so that it satisfies the heap property? To do this we can follow a similar logic as we did for heap pop. We can look at the first node and compare to it's children to see if it's the smallest one, if not swap it with the smaller child. In we already have a function for that called <code>percolateDown()</code>, which we implemented above earlier:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// follows pretty much the same logic as heappush, except minor modifications</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">percolateDown</span>(<span class="hljs-params">heap, index</span>)</span>{
  <span class="hljs-keyword">let</span> curr = index;
  <span class="hljs-comment">// keep going down till heap property is established</span>
  <span class="hljs-keyword">while</span>(<span class="hljs-number">2</span>*curr + <span class="hljs-number">1</span> &lt; heap.length){
    <span class="hljs-keyword">const</span> leftIndex = <span class="hljs-number">2</span>*curr+<span class="hljs-number">1</span>; 
    <span class="hljs-keyword">const</span> rightIndex = <span class="hljs-number">2</span>*curr+<span class="hljs-number">2</span>;
    <span class="hljs-keyword">const</span> minChildIndex = (rightIndex &lt; heap.length &amp;&amp; heap[rightIndex] &lt; heap[leftIndex] ) ? rightIndex :leftIndex;
    <span class="hljs-keyword">if</span>(heap[minChildIndex] &lt; heap[curr]){
     <span class="hljs-comment">// quick swap, if smaller of two children is smaller than the parent (min-heap)</span>
      [heap[minChildIndex], heap[curr]] = [heap[curr], heap[minChildIndex]]
      curr = minChildIndex
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">break</span>
    }
}
</code></pre>
<p>Alright. So now, we can use the <code>percolateDown()</code> function for all items of the array one by one to put everything in correct order as per heap-property. Only important thing</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heapify</span>(<span class="hljs-params">heap</span>)</span>{
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = heap.length<span class="hljs-number">-1</span>; i &gt;= <span class="hljs-number">0</span>; i++){
     percolateDown(heap, i)
   }
  <span class="hljs-keyword">return</span> heap
}
</code></pre>
<p>So that saves us an extra array. But can we do anything to improve time taken? Yes. If you look closely we're actually doing some repetitive work here. Say there are <code>n</code> nodes in heap, out of which <code>x</code> are leaf nodes then that means we only need to perform <code>percolateDown()</code> for <code>n-x</code> nodes, since last <code>x</code> nodes would be in correct place by then.</p>
<p>Great! So in the array representation of heap, till which index we should perform the <code>percolateDown()</code> operation? Well, till the index where parent of the last node lies. Because as soon as parent of last node is percolated down it'll take care of the last node too. So:</p>
<ul>
<li><p>If array length is <code>n</code></p>
</li>
<li><p>Last node's index would be: <code>n-1</code></p>
</li>
<li><p>It's parent node's index would be:</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-built_in">Math</span>.floor((n<span class="hljs-number">-1</span>) - <span class="hljs-number">1</span> / <span class="hljs-number">2</span>) = <span class="hljs-built_in">Math</span>.floor(n/<span class="hljs-number">2</span> - <span class="hljs-number">1</span>)
</code></pre>
<p>Hence our final heapify function would be:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">heapify</span>(<span class="hljs-params">heap</span>) </span>{
  <span class="hljs-keyword">const</span> start = <span class="hljs-built_in">Math</span>.floor((heap.length - <span class="hljs-number">2</span>) / <span class="hljs-number">2</span>); <span class="hljs-comment">// Start at the last parent node</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = start; i &gt;= <span class="hljs-number">0</span>; i--) {
    percolateDown(heap, i);
  }
  <span class="hljs-keyword">return</span> heap;
}
</code></pre>
<h1 id="heading-time-and-space-complexity">Time and space complexity</h1>
<p>Looking at the <code>heappush()</code> and <code>heapop()</code> operation, it's apparent that we're running through the height of the tree while trying to add or remove a key. Since heap is a balanced tree, height is <code>log(n)</code> where n is total number of nodes. Hence for push and pop operations of heap the time complexity would be <code>O(log(n))</code>. The time complexity for <code>heapify()</code> operation may seem like <code>Onlog(n)</code>, since each call takes <code>O(log(n))</code>. This observation is correct for deriving the upper bound of the time complexity for <code>heapify()</code>, however, the asymptotic (averaged) time complexity comes out to be <code>O(n)</code>. More details on this <a target="_blank" href="https://www.geeksforgeeks.org/time-complexity-of-building-a-heap/">here</a>. In terms of space complexity, it's constant, since extra space is only being taken up by the constant-sized variables like <code>curr</code>, <code>leftIndex</code> etc.</p>
<h1 id="heading-what-about-max-heap">What about max-heap?</h1>
<p>If we've an implementation of minHeap we can easily use it as a max heap as well. We just need to ensure that while adding values to the heap we insert negative of the key. It would ensure that heap acts as min-heap for negative of all the keys which is equivalent to maxHeap for all the actual keys. Example:</p>
<ul>
<li><p>Say we have an array <code>const x = [23, 454, 54, 29]</code>;</p>
</li>
<li><p>Min-heap can be created using:</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> heap = [];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> el <span class="hljs-keyword">of</span> x) heappush(heap, el);

<span class="hljs-comment">// min value</span>
<span class="hljs-keyword">const</span> min = heappop(heap)
</code></pre>
<ul>
<li>Max-heap can be created using:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> heap = [];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> el <span class="hljs-keyword">of</span> x) heappush(heap, -el);

<span class="hljs-comment">// max value</span>
<span class="hljs-keyword">const</span> max = -heappop(heap)
</code></pre>
<h1 id="heading-see-it-all-in-action">See it all in action</h1>
<p>Play around with the actual implementation in <a target="_blank" href="https://jspad.dev/?o=0&amp;id=QMk1rMfxk1JH1oF4RUFt&amp;c=2">JSPad</a>:</p>
<p><a target="_blank" href="https://jspad.dev/?o=0&amp;id=QMk1rMfxk1JH1oF4RUFt&amp;c=2"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745517313900/22f3e6c0-1105-4366-a39a-f134065ccaa0.png" alt="JSPad: heap in javascript" class="image--center mx-auto" /></a></p>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[Trie in Javascript: the Data Structure behind Autocomplete]]></title><description><![CDATA[We've already covered the basics of tree data structure in three posts. If you haven't gone through those yet, I would strongly going through the introductory post at the very least.
Introduction
Trie is a variation of tree data structure. It's also ...]]></description><link>https://stackfull.dev/trie-in-javascript-the-data-structure-behind-autocomplete</link><guid isPermaLink="true">https://stackfull.dev/trie-in-javascript-the-data-structure-behind-autocomplete</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[data structures]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[interview]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sun, 24 Oct 2021 15:22:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635077192450/xrhl1Yv8M.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We've already covered the basics of tree data structure in three posts. If you haven't gone through those yet, I would strongly going through the <a target="_blank" href="https://stackfull.dev/tree-data-structure-in-javascript">introductory post</a> at the very least.</p>
<h1 id="heading-introduction">Introduction</h1>
<p>Trie is a variation of tree data structure. It's also referred to as <a target="_blank" href="https://en.wikipedia.org/wiki/Trie">prefix tree</a> or a variation of <a target="_blank" href="https://en.wikipedia.org/wiki/Search_tree">search tree</a>. Just like n-ary tree data structure, a trie can have n children stemming from single parent. Usually all the nodes in a trie would store some character. Assuming we're only dealing with English words, here's how a simple trie may look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635072721112/KBGUbcSZA.png" alt="Screen Shot 2021-10-24 at 4.21.53 PM.png" /></p>
<p>Things to note here:</p>
<ol>
<li><p>We're trying to use a tree to represent English words here, as efficiently as possible.</p>
</li>
<li><p>In the diagram above, a path from root node to any of the green nodes, denotes an English word. For example:</p>
</li>
</ol>
<ul>
<li><p><code>NULL-&gt;C-&gt;A-&gt;T</code>: CAT</p>
</li>
<li><p><code>NULL-&gt;D-&gt;O</code>: DO</p>
</li>
<li><p><code>NULL-&gt;D-&gt;O-&gt;G</code>: DOG</p>
</li>
<li><p><code>NULL-&gt;D-&gt;A-&gt;R-&gt;K</code>: DARK</p>
</li>
<li><p><code>NULL-&gt;A</code>: A</p>
</li>
<li><p><code>NULL-&gt;A-&gt;N</code>: AN</p>
</li>
</ul>
<ol start="3">
<li><p>Each node can have at most 26 children (if we're only dealing with English alphabet). We have a NULL node as root node, because a word can start with any of 26 letters hence we need a dummy node that can have any of potential first letters as a child.</p>
</li>
<li><p>A green node, essentially represents 'end of a word', while traversing from the root till that node.</p>
</li>
</ol>
<h1 id="heading-implement-a-node">Implement a Node</h1>
<p>Nice! So we've got conceptual background. Now, let's try to come up with the programatic representation of the Trie node. Referring back to tree node, this is how we presented it:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Node</span>(<span class="hljs-params">value</span>)</span>{
  <span class="hljs-built_in">this</span>.value = value
  <span class="hljs-built_in">this</span>.left = <span class="hljs-literal">null</span>
  <span class="hljs-built_in">this</span>.right = <span class="hljs-literal">null</span>
}
</code></pre>
<p>So, we can follow a similar idea for Trie while ensuring it meets the requirements we discussed in the Introduction section. To understand requirements of a Trie node, let's zoom in on any of the nodes:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635073632487/S-2XM52nX.png" alt="Screen Shot 2021-10-24 at 4.37.05 PM.png" /></p>
<p>Alright, so it makes more sense now. Here's the final code:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Node</span>(<span class="hljs-params">value</span>)</span>{
  <span class="hljs-built_in">this</span>.value = value
  <span class="hljs-built_in">this</span>.isEndOfWord = <span class="hljs-literal">false</span> <span class="hljs-comment">// false by default, a green node means this flag is true</span>
  <span class="hljs-built_in">this</span>.children = {} <span class="hljs-comment">// children are stored as Map, where key is the letter and value is a TrieNode for that letter </span>
}
</code></pre>
<h1 id="heading-implementing-trie-data-structure">Implementing Trie data structure</h1>
<p>We can represent it using a simple ES6 class:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Trie</span></span>{
  <span class="hljs-keyword">constructor</span>(){
    <span class="hljs-built_in">this</span>.root = <span class="hljs-keyword">new</span> Node(<span class="hljs-literal">null</span>)
  }

  insert(word){
   <span class="hljs-comment">// TODO</span>
  }

  search(word){
   <span class="hljs-comment">// TODO</span>
  }

}
</code></pre>
<p>So we've got the overall interface in place. Each trie would create it's own root node (NULL) as part of initialisation. Then we can implement the two methods as follow:</p>
<ul>
<li><p><code>insert(word)</code>: We can split the word into letters, and create a <code>Node()</code> for each of these letters. Then we can start chaining each of these Trie nodes to the root node , to insert the word. Finally we'll mark the <code>isEndOfWord</code> property as true for last inserted Node.</p>
</li>
<li><p><code>search(word)</code>: We can split the word into letters. Then we can start looking for each of these letters one by one, starting from the root. If we're able to find all the letters sequentially, then we can return true else false.</p>
</li>
</ul>
<p>Let's understand both the operations visually for better context:</p>
<ul>
<li><code>insert(CAR)</code> and then <code>insert(CAN)</code>:</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635075103670/p-OnqTCsT.png" alt="Screen Shot 2021-10-24 at 5.01.35 PM.png" /></p>
<ul>
<li><p><code>search(CODE)</code> and <code>search(CAR)</code>:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635075564931/fjnczE7ml.png" alt="Screen Shot 2021-10-24 at 5.09.13 PM.png" /></p>
</li>
</ul>
<p>Here's how the final implementation would look like:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Trie</span></span>{
  <span class="hljs-keyword">constructor</span>(){
    <span class="hljs-built_in">this</span>.root = <span class="hljs-keyword">new</span> Node(<span class="hljs-literal">null</span>)
  }

  insert(word){
    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.root
    <span class="hljs-comment">// iterate through all the characters of word</span>
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> character <span class="hljs-keyword">of</span> word){
         <span class="hljs-comment">// if node doesn't have the current character as child, insert it</span>
         <span class="hljs-keyword">if</span>(current.children[character] === <span class="hljs-literal">undefined</span>){
             current.children[character] = <span class="hljs-keyword">new</span> Node(character)
         }
        <span class="hljs-comment">// move down, to insert next character</span>
        current = current.children[character]  
    }
    <span class="hljs-comment">// mark the last inserted character as end of the word</span>
    current.isEndOfWord = <span class="hljs-literal">true</span>
  }

  search(word){
     <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.root
    <span class="hljs-comment">// iterate through all the characters of word</span>
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> character <span class="hljs-keyword">of</span> word){
         <span class="hljs-keyword">if</span>(current.children[character] === <span class="hljs-literal">undefined</span>){
             <span class="hljs-comment">// could not find this character in sequence, return false</span>
             <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
         }
        <span class="hljs-comment">// move down, to match next character</span>
        current = current.children[character]  
    }
     <span class="hljs-comment">// found all characters, return true if last character is end of a word</span>
    <span class="hljs-keyword">return</span> current.isEndOfWord
  }
}
</code></pre>
<h1 id="heading-using-a-trie">Using a Trie</h1>
<p>Usage is straightforward. Here's a sample code showing we can use the implementation above:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> trie = <span class="hljs-keyword">new</span> Trie();

<span class="hljs-comment">// insert few words</span>
trie.insert(<span class="hljs-string">"CAT"</span>);
trie.insert(<span class="hljs-string">"DOG"</span>);

<span class="hljs-comment">// search something</span>
trie.search(<span class="hljs-string">"MAT"</span>) <span class="hljs-comment">// false</span>
trie.search(<span class="hljs-string">"DOG"</span>) <span class="hljs-comment">// true</span>
</code></pre>
<p>See it in action in <a target="_blank" href="https://jspad.dev/?c=2&amp;id=NTfCf4ZoD8RPserbfhBI&amp;o=0">JSPad</a>:</p>
<p><a target="_blank" href="https://jspad.dev/?c=2&amp;id=NTfCf4ZoD8RPserbfhBI&amp;o=0"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745515991775/f0ec9c2a-076b-4f7d-8fdb-8039d21d2a4d.png" alt="JSPad: Trie in Javascript" class="image--center mx-auto" /></a></p>
<h1 id="heading-time-and-space-complexity">Time and Space complexity</h1>
<h3 id="heading-space-complexity">Space complexity:</h3>
<p>In the worst case, each character of all inserted words can take up a single node in a Trie. So that would mean worst space complexity can be (W*n), where W is average number of characters per word and n is total number of words in the Trie.</p>
<h3 id="heading-time-complexity">Time complexity:</h3>
<ul>
<li><p>Insert: For inserting a word having <code>n</code> characters, we just need to loop through n characters, so time complexity is <code>O(n)</code></p>
</li>
<li><p>Search: Similar to Insertion, we only need to loop through all the characters of the word to search it. So time complexity is <code>O(n)</code>, where n is number of characters in the word.</p>
</li>
</ul>
<p>Now, step back for a moment and think how else could you search for a word in a huge list of words?</p>
<ul>
<li><p>Probably using an array? Time complexity would be O(m), where where m is total number of words, which is pretty bad.</p>
</li>
<li><p>How about using a map (or an object in JavaScript) ? Well, that would decrease time complexity to O(1), but how fast it would be to find list of words having certain prefix? It would be O(m).</p>
</li>
</ul>
<p>Trie not only brings down the time complexity to O(n) (n = no. of characters in word), but you can also effectively search for a list of words having a prefix, which would be a much more expensive task with any of the two approaches above.</p>
<h1 id="heading-applications">Applications</h1>
<ul>
<li><p><strong>Autocomplete and Typeahead:</strong> If you type something in a text box and you see list of potential searches with same prefix i.e. an Autocomplete widget, then that's probably being handled by a Trie behind the scenes. Similarly <a target="_blank" href="https://en.wikipedia.org/wiki/Typeahead">Typeahead</a> can also be implemented using a Trie.</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Spell_checker">Spell checker</a>: We can use trie to create a spell checker i.e. given a list of words we can check if the spelling of a given word is correct or not.</p>
</li>
<li><p>IP routing (Longest prefix matching): The Internet consists of multiple router nodes which decide the destination packet should be sent. Each router on the Internet needs to send the packet to the appropriate target node decided by the given IP destination. But how each router can decide the next destined router with the given IP address? This problem can be solved using IP routing. Here's a great <a target="_blank" href="https://www.lewuathe.com/longest-prefix-match-with-trie-tree.html">article</a> diving into this subject.</p>
</li>
</ul>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[HTTP Refresher: Things You Should Know About HTTP]]></title><description><![CDATA[HTTP(Hyper Text Transfer Protocol) is one of many protocols used for transferring data (think of html pages, text, images, videos and much more) across machines.  There are other application layer protocols like FTP, SMTP, DHCP etc. 
HTTP was invente...]]></description><link>https://stackfull.dev/http-refresher-things-you-should-know-about-http</link><guid isPermaLink="true">https://stackfull.dev/http-refresher-things-you-should-know-about-http</guid><category><![CDATA[http]]></category><category><![CDATA[webdev]]></category><category><![CDATA[networking]]></category><category><![CDATA[server]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sat, 18 Sep 2021 10:31:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631960609210/DKrxUPpTC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>HTTP(Hyper Text Transfer Protocol) is one of many protocols used for transferring data (think of html pages, text, images, videos and much more) across machines.  There are other application layer protocols like <a target="_blank" href="https://en.wikipedia.org/wiki/File_Transfer_Protocol">FTP</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol">SMTP</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a> etc. </p>
<p>HTTP was invented alongside HTML to create the first interactive, text-based web browser: the original World Wide Web. In this article, we'll be covering the key concepts related to HTTP, which all developers should be aware of.</p>
<h2 id="understanding-the-basics">Understanding the basics</h2>
<p>Let's start with basics  i.e. understanding how data transfer takes place and overall anatomy of HTTP messages.</p>
<h3 id="osi-model">OSI Model</h3>
<p>The OSI (Open Systems Interconnection) is a conceptual framework used to describe the functions of a networking system. It thus helps to see how information is transferred across a network. Here's a diagram depicting various <a target="_blank" href="https://www.comparitech.com/net-admin/osi-model-explained/">networking layers</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631948742808/hzelI0mq5.png" alt="image.png" /></p>
<ul>
<li><strong>Application Layer</strong>:  It's the layer that user interacts with. This layer uses protocols like HTTP and FTP.</li>
<li><p><strong>Presentation Layer</strong> : This layer prepares and translates data from the network format to the application format or vice versa. </p>
</li>
<li><p><strong>Session Layer</strong>: It's the layer responsible for establishing, maintaining, and ending connections between different applications. Typically you’ll see protocols such as NetBios, NFS, RPC, and SQL operating on this layer.</p>
</li>
<li><p><strong>Transport Layer</strong>:  It is the layer responsible for transferring data between end systems and hosts. It dictates what gets sent where, and how much of it gets sent. At this level, you see protocols like TCP, UDP, and SPX.</p>
</li>
<li><p><strong>Network Layer</strong>: It has the job of dealing with most of the routing within a network. In simple terms, the Network Layer determines how a packet travels to its destination. Protocols like TCP/IP, AppleTalk, and IPX operate at this layer.</p>
</li>
<li><p><strong>Data Link Layer</strong>: The data link provides for the transfer of data frames between hosts connected to the physical link.</p>
</li>
<li><p><strong>Physical Layer</strong>: It is the hardware layer of the OSI model which includes network elements such as hubs, cables, ethernet, and repeaters. For example, this layer is responsible for executing electrical signal changes like making lights light up.</p>
</li>
</ul>
<h3 id="http-messages">HTTP messages</h3>
<p>As mentioned above, HTTP operates in application layer i.e. the layer user directly interacts with. Some key points regarding this protocol:</p>
<ul>
<li>HTTP follows the classical <a target="_blank" href="https://en.wikipedia.org/wiki/Client%E2%80%93server_model">client-server model</a>. A client opens a connection to issue a request and then waits for the server to respond.</li>
<li>HTTP is a <a target="_blank" href="https://en.wikipedia.org/wiki/Stateless_protocol">stateless protocol</a> i.e. each request has isolated and independent lifecycle. HTTP is not session-less though. For example, HTTP cookies allow the use of stateful sessions.</li>
<li>HTTP, which is an application layer protocol, rides on top of <a target="_blank" href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP (Transmission Control Protocol)</a>: a transport layer protocol.</li>
<li>HTTP is <a target="_blank" href="https://stackoverflow.com/questions/393407/why-http-protocol-is-designed-in-plain-text-way">text based protocol</a> i.e data transmission takes place using text format.</li>
</ul>
<h2 id="http-requestresponse-anatomy">HTTP request/response anatomy</h2>
<p>An HTTP request can consist of four parts: </p>
<ul>
<li>Request method</li>
<li>URL</li>
<li>Request headers</li>
<li>Request body</li>
</ul>
<p>These are the possible HTTP request methods:</p>
<ul>
<li><strong>GET</strong> requests a specific resource in its entirety</li>
<li><strong>HEAD</strong> requests a specific resource without the body content</li>
<li><strong>POST</strong> adds content, messages, or data to a new page under an existing web resource</li>
<li><strong>PUT</strong> directly modifies an existing web resource or creates a new URI if need be</li>
<li><strong>DELETE</strong> gets rid of a specified resource</li>
<li><strong>TRACE</strong> shows users any changes or additions made to a web resource</li>
<li><strong>OPTIONS</strong> shows users which HTTP methods are available for a specific URL</li>
<li><strong>CONNECT</strong> converts the request connection to a transparent TCP/IP tunnel</li>
<li><strong>PATCH</strong> partially modifies a web resource</li>
</ul>
<p>An HTTP request is just a series of lines of text that follow the HTTP protocol. A GET request might look like this:</p>
<pre><code class="lang-text">GET /hello.txt HTTP/1.1
User-Agent: curl/7.63.0 libcurl/7.63.0 OpenSSL/1.1.l zlib/1.2.11
Host: www.example.com
Accept-Language: en
</code></pre>
<p>Once the server receives the request, It may respond with some data. A sample HTTP response would like this:</p>
<pre><code class="lang-text">HTTP/1.1 200 OK
Date: Wed, 30 Jan 2019 12:14:39 GMT
Server: Apache
Last-Modified: Mon, 28 Jan 2019 11:17:01 GMT
Accept-Ranges: bytes
Content-Length: 12
Vary: Accept-Encoding
Content-Type: text/plain

Hello World!
</code></pre>
<h3 id="http-and-security-concern">HTTP and security concern</h3>
<p>As stated earlier, HTTP uses text format for data transmission. The problem is this data is not encrypted, so it can be intercepted by third parties to gather data being passed between the two systems. This issue can be addressed using HTTPS.</p>
<h3 id="what-is-https">What is HTTPS?</h3>
<p>The S in HTTPS stands for "secure." HTTPS uses <a target="_blank" href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS</a> (or SSL) to encrypt HTTP requests and responses, so in the example above, instead of the text, an attacker would see a bunch of seemingly random characters.</p>
<p>Instead of:</p>
<pre><code class="lang-text">GET /hello.txt HTTP/1.1
User-Agent: curl/7.63.0 libcurl/7.63.0 OpenSSL/1.1.l zlib/1.2.11
Host: www.example.com
Accept-Language: en
</code></pre>
<p>The attacker would see something like:</p>
<pre><code class="lang-text">t8Fw6T8UV81pQfyhDkhebbz7+oiwldr1j2gHBB3L3RFTRsQCpaSnSBZ78Vme+DpDVJPvZdZUZHpzbbcqmSW1+dkughdkhkuyi2u3gsJGSJHF/FNUjgH0BmVRWII6+T4MnDwmCMZUI/orxP3HGwYCSIvyzS3MpmmSe4iaWKCOHQ==
</code></pre>
<h3 id="how-tls-encrypts-http-messages">How TLS encrypts HTTP messages</h3>
<p>TLS uses a technology called <a target="_blank" href="https://www.geeksforgeeks.org/public-key-encryption/">public key encryption</a>. In a nutshell:</p>
<ul>
<li>There are two keys, a public key and a private key.</li>
<li>The public key is shared with client devices via the server's SSL certificate. </li>
<li>When a client opens a connection with a server, the two devices use the public and private key to agree on new keys, called session keys, to encrypt further communications between them.</li>
<li>All HTTP requests and responses are then encrypted with these session keys, so that anyone who intercepts communications can only see a random string of characters, not the plaintext.</li>
</ul>
<p>You can find a great article on encryption <a target="_blank" href="https://www.cloudflare.com/learning/ssl/what-is-encryption/">here</a> if that interests you.</p>
<h2 id="evolution-of-http">Evolution of HTTP</h2>
<p>The protocol was developed by Tim Berners-Lee and his team between 1989-1991.  The first version: HTTP/0.9 is also referred to as one line protocol. Only <code>GET</code> request type was supported back then. HTTP/0.9 was very limited and both browsers and servers quickly extended it to be more versatile, resulting in HTTP/1.0. </p>
<p>HTTP/1.0 brought in quite a few novelties. It introduced concepts of status code, multiple request methods(<code>GET</code> , <code>HEAD</code>, <code>POST</code>), request/response headers etc.</p>
<h3 id="lack-of-persistence">Lack of Persistence</h3>
<p>HTTP/1.0 required to open up a new TCP connection for each request (and close it immediately after the response was sent). 
TCP connection in turn uses a <strong>three-way handshake</strong> to establish a reliable connection. The connection is full duplex(two way connection), and both sides synchronize (SYN) and acknowledge (ACK) each other. The exchange of these four flags is performed in three steps—SYN, SYN-ACK, and ACK—as shown in Figure:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631954774758/pBBcHQFCG.png" alt="image.png" /></p>
<p>For better performance, it was crucial to reduce these round-trips between client and server. HTTP/1.1 solved this with <strong>persistent connections</strong>. What's a persistent connection? It's a (network communication) channel that remains open for further HTTP requests and responses rather than closing after a single exchange.</p>
<h3 id="keep-alive-header">Keep-Alive header</h3>
<p><code>keep-alive</code> header was added to HTTP 1.0 to facilitate persistent connection. If the client supports <code>keep-alive</code>, it adds an additional header to the request:</p>
<pre><code><span class="hljs-keyword">Connection</span>: keep-alive
</code></pre><p>Then, when the server receives this request and generates a response, it also adds a header to the response:</p>
<pre><code><span class="hljs-keyword">Connection</span>: keep-alive
</code></pre><p>Following this, the connection is not dropped, but is instead kept open. When the client sends another request, it uses the same connection. This will continue until either the client or the server decides that the conversation is over, and one of them drops the connection.</p>
<h2 id="http11">HTTP/1.1</h2>
<p>HTTP/1.1 Introduced critical performance optimizations and feature enhancements. Major offerings are listed below:</p>
<h3 id="persistent-and-pipelined-connections">Persistent and pipelined connections</h3>
<ul>
<li><p><strong>Persistence:</strong> In HTTP 1.1, all connections are considered persistent unless declared otherwise. The HTTP persistent connections do not use separate <code>keep-alive</code> messages, they just allow multiple requests to use a single connection by default.</p>
</li>
<li><p><strong>Pipelining:</strong> is the process of sending successive requests, over the same persistent connection, without waiting for the answer. This avoids latency of the connection.  </p>
</li>
</ul>
<p>The image below illustrates difference between short lived, persistent and pipelined connections.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631975902031/_irYKYWhD.png" alt="Screen Shot 2021-09-18 at 8.06.58 PM.png" /></p>
<ul>
<li><strong> Head of line blocking</strong>: Even though pipelining reduces number of requests and re-uses same connection, it still requires the responses to arrive in order. Which means if the first request takes too long to be responded, subsequent requests remain blocked. This is called "Head of line blocking". HTTP/2.0 sloves this using <strong>binary framing</strong> without sacrificing parallelism. More on this is discussed ahead in this article.</li>
</ul>
<h3 id="chunked-transfers-encoding">Chunked transfers encoding</h3>
<p><code>keep-alive</code> makes it difficult for the client to determine where one response ends and the next response begins, particularly during pipelined HTTP operation. This is a serious problem when <code>Content-Length</code> cannot be used due to streaming. To solve this problem, HTTP 1.1 introduced a chunked transfer coding that defines a last-chunk bit. The last-chunk bit is set at the end of each response so that the client knows where the next response begins.</p>
<h3 id="compression-and-decompression">Compression and Decompression</h3>
<p>HTTP/1.1 introduced headers that allow transfer of compressed data over the network. It can be done with the help of <code>Accept-Encoding</code> and <code>Content-Encoding</code> headers. Here's summary of how it works:</p>
<ul>
<li>Client issues request with <code>Accept-Encoding</code> header to let server understand the compression schemes it supports:<pre><code class="lang-text">GET /encrypted-area HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip, deflate
</code></pre>
</li>
<li>If server supports any these compression schemes, it can choose to compress the content and respond with it along with <code>Content-Encoding</code> header:<pre><code class="lang-text">HTTP/1.1 200 OK
Date: mon, 26 June 2016 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix)  (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
</code></pre>
</li>
</ul>
<p>HTTP/1.1 Also introduced following concepts:</p>
<ul>
<li><strong>Virtual hosting:</strong> a server with a single IP Address hosting multiple domains</li>
<li><strong>Cache support:</strong> faster response and great bandwidth savings by adding cache support.</li>
</ul>
<h2 id="http20">HTTP/2.0</h2>
<p>HTTP/2 is a major revision of the HTTP protocol. It was derived from the earlier experimental <a target="_blank" href="https://en.wikipedia.org/wiki/SPD">SPDY</a> protocol, originally developed by Google. </p>
<h3 id="http2-is-binary-instead-of-textual">HTTP2 is <strong>binary</strong>, instead of textual</h3>
<p>At the core of all performance enhancements of HTTP/2 is the new binary framing layer, which dictates how the HTTP messages are encapsulated and transferred between the client and server. Following are the critical terms associated with framing layer:</p>
<ul>
<li><p><strong>Frame</strong>: The <strong>smallest unit of communication</strong> in HTTP/2, each containing a frame header, which at a minimum identifies the stream to which the frame belongs.</p>
</li>
<li><p><strong>Message</strong>: A complete <strong>sequence of frames</strong> that map to a logical request or response message.</p>
</li>
<li><p><strong>Stream</strong>: A bidirectional flow of bytes within an established connection, which may carry <strong>one or more messages</strong> in it.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631958924830/WqtNgMwdi.png" alt="Screen Shot 2021-09-18 at 3.24.57 PM.png" /></p>
<p>The image below illustrates how an HTTP/1.x message compares to HTTP/2.0 message (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages">Source</a>):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631975935565/hzKruDE2l.png" alt="Screen Shot 2021-09-18 at 8.07.06 PM.png" /></p>
<h3 id="multiplexing">Multiplexing</h3>
<p>In HTTP/2.0, client and server can break down an HTTP message into independent frames, interleave them, and then reassemble them on the other end. This is called multiplexing. It can be understood better by the diagram below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631959233801/4_jJaIYKd1.png" alt="Screen Shot 2021-09-18 at 3.30.27 PM.png" /></p>
<h3 id="parallelism-one-connection-per-origin">Parallelism: One connection per origin</h3>
<p>With the new binary framing mechanism in place, HTTP/2 no longer needs multiple TCP connections to multiplex streams in parallel; each stream is split into many frames, which can be interleaved and prioritized. As a result, all HTTP/2 connections are persistent, and only one connection per origin is required, which offers numerous performance benefits.</p>
<h3 id="server-push">Server push</h3>
<p>Another powerful new feature of HTTP/2 is the ability of the server to send multiple responses for a single client request. That is, in addition to the response to the original request, the server can push additional resources to the client without the client having to request each one explicitly.</p>
<blockquote>
<p>Server push is intended to be deprecated. More details on <a target="_blank" href="https://groups.google.com/a/chromium.org/g/blink-dev/c/K3rYLvmQUBY/m/vOWBKZGoAQAJ?pli=1">this post</a>, shared by the chromium team.</p>
</blockquote>
<h2 id="future-of-http-http30">Future of HTTP: HTTP/3.0</h2>
<p>HTTP/3.0 is the upcoming major version of HTTP. So far the underlying transport layer mechanism behind HTTP has been TCP.  HTTP/3.0 changes that, even though the core semantics remain unchanged.</p>
<p>The fundamental difference between HTTP/2 and HTTP/3 is that HTTP/3 runs over <a target="_blank" href="https://en.wikipedia.org/wiki/QUIC">QUIC</a>, and QUIC runs over connectionless <a target="_blank" href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a> instead of the connection-oriented TCP.</p>
<p>Another significant different is HTTP/3.0 mandates secure transfer of data. HTTP/3 includes encryption that borrows heavily from TLS but isn’t using it directly. This change is because HTTP/3 differs from HTTPS/TLS in terms of what it encrypts: </p>
<ul>
<li>With the older HTTPS/TLS protocol, only the data itself is protected by TLS, leaving a lot of the transport metadata visible. </li>
<li>In HTTP/3 both the data and the transport protocol are protected. </li>
</ul>
<blockquote>
<p>Note: Most browsers do not support h2c (HTTP/2 without TLS), which means opting for HTTP/2.0 pretty much needs you to opt for TLS if you're hosting a website. Here's a relevant <a target="_blank" href="https://stackoverflow.com/questions/46788904/why-do-web-browsers-not-support-h2c-http-2-without-tls">stackoverlow thread</a> on why browsers act this way.</p>
</blockquote>
<p>The diagram below illustrates fundamental difference between HTTP/3.0 and it's predecessor(<a target="_blank" href="https://ably.com/topic/http-2-vs-http-3">source</a>):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631965955142/AiWibfxf4.png" alt="image.png" /></p>
<h3 id="references">References:</h3>
<ul>
<li>https://www.developer.mozilla.org/en-US/docs/Web/HTTP/Connection_management_in_HTTP_1.x</li>
<li>https://www.en.wikipedia.org/wiki/HTTP_compression</li>
<li>https://www.greenlanemarketing.com/resources/articles/seo-101-http-vs-http2/</li>
<li>https://developers.google.com/web/fundamentals/performance/http2</li>
<li>https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages</li>
<li>https://developer.okta.com/books/api-security/tls/how/</li>
</ul>
<div class="hn-embed-widget" id="message"></div><p>.</p>
]]></content:encoded></item><item><title><![CDATA[Design patterns in Javascript: Publish-Subscribe or PubSub]]></title><description><![CDATA[What's a design pattern in software engineering? It's a general repeatable solution to a commonly occurring problem in software design. In this article, we'll be looking at one of such common design patterns and see how it can be put to use in real w...]]></description><link>https://stackfull.dev/design-patterns-in-javascript-publish-subscribe-or-pubsub-1</link><guid isPermaLink="true">https://stackfull.dev/design-patterns-in-javascript-publish-subscribe-or-pubsub-1</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[software development]]></category><category><![CDATA[Redux]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Tue, 14 Sep 2021 02:33:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631586779333/UN1ZFzj9u.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What's a design pattern in software engineering? It's a <strong>general repeatable solution</strong> to a commonly occurring problem in software design. In this article, we'll be looking at one of such common design patterns and see how it can be put to use in real world applications.</p>
<p>This pattern is referred to as Publish-Subscribe or PubSub. Let's start with the overall notion behind this pattern before writing some code.</p>
<h2 id="overview">Overview</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1631540738187/qmkcqTo2D.png" alt="pubsub.png" /></p>
<p>The image above describes the general idea behind this pattern:</p>
<ul>
<li>We have a PubSub 'container' that maintains a list of <code>subscribers</code> (a subscriber is just a function)</li>
<li>A new subscription can be created by using the <code>subscribe(subscriber)</code> method, which essentially adds the <code>subscriber</code> into our PubSub container</li>
<li>We can use <code>publish(payload)</code> to call all the existing <code>subscribers</code> in the PubSub container with <code>payload</code></li>
<li>Any specific <code>subscriber</code> can be removed from the container, at any point in time, using the <code>unsubscribe(subscriber)</code> method.</li>
</ul>
<h2 id="implementation">Implementation</h2>
<p>Looking at the points above it's pretty straightforward to come up with a simple implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// pubsub.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PubSub</span> </span>{
  <span class="hljs-keyword">constructor</span>(){
    <span class="hljs-comment">// this is where we maintain list of subscribers for our PubSub</span>
    <span class="hljs-built_in">this</span>.subscribers = []
  }

  subscribe(subscriber){
    <span class="hljs-comment">// add the subscriber to existing list</span>
    <span class="hljs-built_in">this</span>.subscribers = [...this.subscribers, subscriber]
  }

  unsubscribe(subscriber){
   <span class="hljs-comment">// remove the subscriber from existing list</span>
    <span class="hljs-built_in">this</span>.subscribers = <span class="hljs-built_in">this</span>.subscribers.filter(<span class="hljs-function"><span class="hljs-params">sub</span> =&gt;</span> sub!== subscriber)
  }

  publish(payload){
   <span class="hljs-comment">// publish payload to existing subscribers by invoking them</span>
    <span class="hljs-built_in">this</span>.subscribers.forEach(<span class="hljs-function"><span class="hljs-params">subscriber</span> =&gt;</span> subscriber(payload))
  }
}
</code></pre>
<p>Let's add a bit of error handling to this implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// pubsub.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PubSub</span> </span>{
  <span class="hljs-keyword">constructor</span>(){
    <span class="hljs-built_in">this</span>.subscribers = []
  }

  subscribe(subscriber){
    <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> subscriber !== <span class="hljs-string">'function'</span>){
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">typeof</span> subscriber}</span> is not a valid argument for subscribe method, expected a function instead`</span>)
    }
    <span class="hljs-built_in">this</span>.subscribers = [...this.subscribers, subscriber]
  }

  unsubscribe(subscriber){
    <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> subscriber !== <span class="hljs-string">'function'</span>){
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">typeof</span> subscriber}</span> is not a valid argument for unsubscribe method, expected a function instead`</span>)
    }
    <span class="hljs-built_in">this</span>.subscribers = <span class="hljs-built_in">this</span>.subscribers.filter(<span class="hljs-function"><span class="hljs-params">sub</span> =&gt;</span> sub!== subscriber)
  }

  publish(payload){
    <span class="hljs-built_in">this</span>.subscribers.forEach(<span class="hljs-function"><span class="hljs-params">subscriber</span> =&gt;</span> subscriber(payload))
  }
}
</code></pre>
<h2 id="usage">Usage</h2>
<p>We can use this implementation as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.js</span>
<span class="hljs-keyword">import</span> PubSub <span class="hljs-keyword">from</span> <span class="hljs-string">'./PubSub'</span>;

<span class="hljs-keyword">const</span> pubSubInstance = <span class="hljs-keyword">new</span> PubSub();

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> pubSubInstance
</code></pre>
<p>Now, elsewhere in the application, we can publish and subscribe using this instance:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//app.js</span>
<span class="hljs-keyword">import</span> pubSubInstance <span class="hljs-keyword">from</span> <span class="hljs-string">'./main.js'</span>;

pubSubInstance.subscribe(<span class="hljs-function"><span class="hljs-params">payload</span> =&gt;</span> {
  <span class="hljs-comment">// do something here</span>
  showMessage(payload.message)
})
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">// home.js</span>
<span class="hljs-keyword">import</span> pubSubInstance <span class="hljs-keyword">from</span> <span class="hljs-string">'./main.js'</span>;

pubSubInstance.publish({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Hola!'</span> });
</code></pre>
<h2 id="is-it-useful-in-real-applications">Is it useful in real applications?</h2>
<p>Yes. In fact, there are many libraries that use it under the hood and you may not have realized it so far.  Let's take the example of the popular state management library for ReactJS - <strong>Redux</strong>. Of course, its implementation is not as simple as ours, since it's been implemented to handle many other nuances and use-cases. Nevertheless, the underlying concept remains the same.</p>
<p>Looking at the <a target="_blank" href="http://redux.js.org/docs/api/Store.html#store-methods">methods offered by Redux</a>, You would see <code>dispatch()</code> and <code>subscribe()</code> methods which are equivalent to <code>publish()</code> and <code>subscribe()</code> methods we implemented above. You usually won't see <code>subscribe()</code> method getting used directly, this part is abstracted away behind <code>connect()</code> method offered by react-redux library. You can follow the implementation details <a target="_blank" href="https://github.com/reduxjs/react-redux/blob/4.x/src/components/connect.js#L199">here</a> if that interests you. </p>
<p>In summary, all react components using <code>connect()</code> method act as subscribers. Any component using <code>dispatch()</code> acts as the publisher. And that explains why dispatching an action from any component causes all <code>connected</code> components to rerender. </p>
<h2 id="whats-next">What's next</h2>
<ul>
<li>We'll see how the idea behind PubSub can be extended further to build a state management library like redux from scratch.</li>
<li>We'll also see how an Event Emitter can be built from scratch, using similar notion as PubSub</li>
</ul>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[Applying tree traversal algorithms to DOM]]></title><description><![CDATA[We've looked through few binary tree traversal techniques so far:
1- Traversing through the binary tree using recursive and iterative algorithms
2- Traversing through the binary tree using parent pointers
In this article, we'll put those learnings to...]]></description><link>https://stackfull.dev/applying-tree-traversal-algorithms-to-dom</link><guid isPermaLink="true">https://stackfull.dev/applying-tree-traversal-algorithms-to-dom</guid><category><![CDATA[algorithms]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Tue, 31 Aug 2021 05:24:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630374204354/Uo6yqKI4Z.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We've looked through few binary tree traversal techniques so far:</p>
<p>1- <a target="_blank" href="https://stackfull.dev/tree-data-structure-in-javascript">Traversing through the binary tree using recursive and iterative algorithms</a></p>
<p>2- <a target="_blank" href="https://stackfull.dev/tree-efficient-traversal-with-parent-pointer">Traversing through the binary tree using parent pointers</a></p>
<p>In this article, we'll put those learnings to use for an n-ary tree i.e. DOM. We'll see how we can locate DOM elements using various CSS selectors without using inbuilt APIs like <code>getElementById</code>, <code>getElementsByClassname</code> or <code>querySelector</code>/<code>querySelectorAll</code>. The article would thus also throw light on how these APIs might be working under the hood.</p>
<h2 id="dom-traversal-overview">DOM traversal overview</h2>
<p>Borrowing the idea from the first article, let's come up with the preOrder traversal algorithm for DOM:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkPreOrder</span>(<span class="hljs-params">node</span>)</span>{
  <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

  <span class="hljs-comment">// do something here</span>
  <span class="hljs-built_in">console</span>.log(node)

  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> child <span class="hljs-keyword">of</span> node.children){
     walkPreOrder(child)
  }
}
</code></pre>
<p>We can modify this algorithm to return an iterator instead:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">walkPreOrder</span>(<span class="hljs-params">node</span>)</span>{
  <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

  <span class="hljs-comment">// do something here</span>
  <span class="hljs-keyword">yield</span> node
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> child <span class="hljs-keyword">of</span> node.children){
    <span class="hljs-keyword">yield</span>* walkPreOrder(child)
  }
}

<span class="hljs-comment">// USAGE</span>
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(root)){
  <span class="hljs-built_in">console</span>.log(node)
}
</code></pre>
<p>We can use any of the breadth-first or depth-first algorithms (discussed in previous articles) to traverse the DOM. For the sake of this article, we'll stick with the above approach though.  </p>
<p>Let's also assume we're working on a document having following HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>DOM selection algorithm<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"body"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"profile"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"xyz.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="locating-a-node-by-id">Locating a node by ID</h3>
<p>Browsers offer <code>document.getElementById()</code> API to achieve this result. Using the <code>walkPreOrder()</code> helper it becomes really simple to achieve this. Let's see:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">locateById</span>(<span class="hljs-params">nodeId</span>)</span>{
  <span class="hljs-comment">// iterate through all nodes in depth first (preOrder) fashion</span>
  <span class="hljs-comment">// return the node as soon as it's found</span>
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(<span class="hljs-built_in">document</span>.body)){
     <span class="hljs-keyword">if</span>(node.id === nodeId){
        <span class="hljs-keyword">return</span> node
     }
  }
   <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
}
</code></pre>
<p>We can use the <code>locateById()</code> function as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> img = locateById(<span class="hljs-string">'profile'</span>)
<span class="hljs-comment">// returns the image node</span>
</code></pre>
<h3 id="locating-nodes-by-classname">Locating nodes by className</h3>
<p>Browsers offer <code>document.getElementsByClassName()</code> API to achieve this result. Let's see how we can implement something similar: </p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">locateAllByClassName</span>(<span class="hljs-params">className</span>)</span>{
   <span class="hljs-keyword">const</span> result = []
   <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(<span class="hljs-built_in">document</span>.body)){
      <span class="hljs-keyword">if</span>(node.classList.contains(className)){
        result.push(node)
      }
   }
   <span class="hljs-keyword">return</span> result
}

<span class="hljs-comment">// USAGE</span>
<span class="hljs-keyword">const</span> elements = locateAllByClassName(<span class="hljs-string">'row'</span>)
</code></pre>
<h3 id="how-browser-optimizes-the-selection-queries">How browser optimizes the selection queries</h3>
<p>Selecting DOM nodes is a fairly common operation for web applications. Traversing through the tree multiple times for the same selector doesn't seem optimal.  Browser optimizes the selection by using memoization. </p>
<p>Looking at mozilla <a target="_blank" href="https://searchfox.org/mozilla-central/source/parser/html/javasrc/TreeBuilder.java#1467">parser's source</a>, namely an excerpt from the function startTag:</p>
<pre><code class="lang-java"> <span class="hljs-comment">// ID uniqueness</span>
 <span class="hljs-meta">@IdType</span> String id = attributes.getId();
 <span class="hljs-keyword">if</span> (id != <span class="hljs-keyword">null</span>) {
      LocatorImpl oldLoc = idLocations.get(id);
      <span class="hljs-keyword">if</span> (oldLoc != <span class="hljs-keyword">null</span>) {
            err(<span class="hljs-string">"Duplicate ID \u201C"</span> + id + <span class="hljs-string">"\u201D."</span>);
            errorHandler.warning(<span class="hljs-keyword">new</span> SAXParseException(
                  <span class="hljs-string">"The first occurrence of ID \u201C"</span> + id
                  + <span class="hljs-string">"\u201D was here."</span>, oldLoc));
       } <span class="hljs-keyword">else</span> {
            idLocations.put(id, <span class="hljs-keyword">new</span> LocatorImpl(tokenizer));
       }
 }
</code></pre>
<p>We can see those node ids are kept in a simple hash map. We can use a similar approach to ensure repeated queries for the same ID do not require full traversal, instead, we can just look it up from hashMap and return it.</p>
<p>Here's how our solution would look like post memoization:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getSelectors</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">const</span> idLocations = {}
  <span class="hljs-keyword">const</span> classLocations = {}

  <span class="hljs-comment">// updated selector functions  </span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">locateById</span>(<span class="hljs-params">nodeId</span>)</span>{
    <span class="hljs-keyword">if</span>(idLocations.hasOwnProperty(nodeId)) 
       <span class="hljs-keyword">return</span> idLocations[nodeId]

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(<span class="hljs-built_in">document</span>.body)){
       <span class="hljs-keyword">if</span>(node.id === nodeId){
          idLocations[nodeId]= node <span class="hljs-comment">//memoize</span>
          <span class="hljs-keyword">return</span> node
       }
     }
    idLocations[nodeId]= <span class="hljs-literal">null</span> <span class="hljs-comment">// memoize</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">locateAllByClassName</span>(<span class="hljs-params">className</span>)</span>{
    <span class="hljs-keyword">if</span>(classLocations.hasOwnProperty(className)) 
         <span class="hljs-keyword">return</span> classLocations[className]

    <span class="hljs-keyword">const</span> result = []
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(<span class="hljs-built_in">document</span>.body)){
       <span class="hljs-keyword">if</span>(node.classList.contains(className)){
          result.push(node)
        }
     }
     classLocations[nodeId]= result
     <span class="hljs-keyword">return</span> result
  }

  <span class="hljs-keyword">return</span> {
       locateById,
       locateAllByClassName
    }

} 

  <span class="hljs-comment">// USAGE</span>
  <span class="hljs-keyword">const</span> {locateById, locateAllByClassName} = getSelectors();
  <span class="hljs-keyword">const</span> result = locateAllByClassName(<span class="hljs-string">'row'</span>) <span class="hljs-comment">// returns array of elements</span>
  <span class="hljs-keyword">const</span> img = locateById(<span class="hljs-string">'profile'</span>) <span class="hljs-comment">// returns an element, if found</span>
</code></pre>
<h2 id="dealing-with-more-complex-selectors">Dealing with more complex selectors</h2>
<p>Let's try to implement something like <code>element.querySelector</code>. Here's how MDN describes it:</p>
<blockquote>
<p>The querySelector() method of the Element interface returns the first element that is a descendant of the element on which it is invoked that matches the specified group of selectors.</p>
</blockquote>
<p>Example: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> firstRow = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.container .row:first-child'</span>)
</code></pre>
<p>In this case we can pass any CSS selector to the function and it should be able to traverse the DOM to find that element for us. Let's see it we how it can be implemented:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// given a selector and root node, find that selector within the root node</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">select</span>(<span class="hljs-params">selector, root</span>)</span>{
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(root)){
      <span class="hljs-keyword">if</span>(node.matches(selector)){
        <span class="hljs-keyword">return</span> node
     }
   }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myQuerySelector</span>(<span class="hljs-params">path, node</span>)</span>{
  <span class="hljs-comment">// if path is empty, nothing to find</span>
  <span class="hljs-keyword">if</span>(path.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-comment">// if node is not provided, let's assume user wants to search within document.body</span>
  <span class="hljs-keyword">let</span> root = node || <span class="hljs-built_in">document</span>.body;  
  <span class="hljs-keyword">const</span> selector = path[<span class="hljs-number">0</span>];

  <span class="hljs-comment">// if there's only one selector in the path, just traverse using select function above</span>
  <span class="hljs-keyword">if</span>(path.length === <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> select(selector, root);

   <span class="hljs-comment">// else, either the current node matches the first selector in path or not</span>
   <span class="hljs-comment">// if first selector matches with current node, look through it's children for subsequent selectors only</span>
   <span class="hljs-comment">// else, look through it's children for the whole path</span>
  <span class="hljs-keyword">const</span> newPath = root.matches(selector) ? path.slice(<span class="hljs-number">1</span>): path;
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> child <span class="hljs-keyword">of</span> root.children){
    <span class="hljs-keyword">const</span> ans = myQuerySelector(newPath, child);
    <span class="hljs-keyword">if</span>(ans) <span class="hljs-keyword">return</span> ans
  }

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


<span class="hljs-comment">// USAGE:</span>
<span class="hljs-keyword">const</span> firstRow = myQuerySelector([<span class="hljs-string">".container"</span>, <span class="hljs-string">".row"</span>])
</code></pre>
<p>Implementation of <code>myQuerySelectorAll</code> (similar to <code>element.querySelectorAll</code>) also follows the same approach with slight modification:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAll</span>(<span class="hljs-params">selector, root</span>)</span>{
  <span class="hljs-keyword">let</span> result = []
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(root)){
      <span class="hljs-keyword">if</span>(node.matches(selector)){
        result.push(node)
     }
   }
  <span class="hljs-keyword">return</span> result;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myQuerySelectorAll</span>(<span class="hljs-params">path, node</span>)</span>{
  <span class="hljs-keyword">let</span> result = [];
  <span class="hljs-keyword">if</span>(path.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> result;

  <span class="hljs-keyword">let</span> root = node || <span class="hljs-built_in">document</span>.body;  
  <span class="hljs-keyword">const</span> selector = path[<span class="hljs-number">0</span>];

  <span class="hljs-keyword">if</span>(path.length === <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> selectAll(selector, root);

  <span class="hljs-keyword">const</span> newPath = root.matches(selector) ? path.slice(<span class="hljs-number">1</span>): path;
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> child <span class="hljs-keyword">of</span> root.children){
    result = [...result, ...myQuerySelectorAll(newPath, child)]

  }

  <span class="hljs-keyword">return</span> result;
}
</code></pre>
<h2 id="bonus">Bonus</h2>
<p>We can use the recursive preOrder traversal approach, describe at the start of this article, to clone any tree. Let's see how we can use it to clone any DOM tree, similar to what <code>element.cloneNode(true)</code> does:</p>
<ul>
<li>Create a clone of the source node, by creating a new node with the same tagName and then copying over the attributes.</li>
<li>Recursively call the <code>cloneTree</code> method on all children of the source node, and append the returned nodes as children to the cloned node.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cloneTree</span>(<span class="hljs-params">node</span>)</span>{
  <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> clonedNode = <span class="hljs-built_in">document</span>.createElement(node.tagName.toLowerCase())
  <span class="hljs-keyword">const</span> attributes = node.getAttributeNames()

  attributes.forEach(<span class="hljs-function"><span class="hljs-params">attribute</span> =&gt;</span> {
     clonedNode.setAttribute(attribute, node.getAttribute(attribute))
  })

  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> child <span class="hljs-keyword">of</span> node.children){
      clonedNode.append(cloneTree(child))
  }

  <span class="hljs-keyword">return</span> clonedNode
}
</code></pre>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[Memoizing async functions in Javascript]]></title><description><![CDATA[Memoization is a useful concept. It helps avoid time taking or expensive calculations after it's been done once. Applying memoization to a synchronous function is relatively straightforward. This article aims to introduce the overall concept behind m...]]></description><link>https://stackfull.dev/memoizing-async-functions-in-javascript</link><guid isPermaLink="true">https://stackfull.dev/memoizing-async-functions-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[fetch]]></category><category><![CDATA[APIs]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sun, 29 Aug 2021 02:39:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630204896641/k9XriUD8n.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Memoization is a useful concept. It helps avoid time taking or expensive calculations after it's been done once. Applying memoization to a synchronous function is relatively straightforward. This article aims to introduce the overall concept behind memoization and then dive into the problems and their solutions while trying to memoize async functions. </p>
<h2 id="memoization">Memoization</h2>
<p>Let's start with memoizing a pure function. Let's say we have a function called <code>getSquare</code>, which returns the square of the given:</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getSquare</span>(<span class="hljs-params">x</span>)</span>{
     <span class="hljs-keyword">return</span> x * x
  }
</code></pre>
<p>To memoize this we can do something like this:</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">const</span> memo = {}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getSquare</span>(<span class="hljs-params">x</span>)</span>{
    <span class="hljs-keyword">if</span>(memo.hasOwnProperty(x)) {
      <span class="hljs-keyword">return</span> memo[x]
    }
    memo[x] = x * x
    <span class="hljs-keyword">return</span> memo[x]
}
</code></pre>
<p>So, with few lines of code, we've memoized our <code>getSquare</code> function. </p>
<p>Let's create a <code>memoize</code> helper. It would  accept a pure function as the first argument and a<code>getKey</code> function (which returns a unique key given argument of the function) as the second argument, to return a memoized version of the function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoize</span>(<span class="hljs-params">fn, getKey</span>)</span>{
  <span class="hljs-keyword">const</span> memo = {}
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoized</span>(<span class="hljs-params">...args</span>)</span>{
     <span class="hljs-keyword">const</span> key = getKey(...args)
     <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)) <span class="hljs-keyword">return</span> memo[key]

     memo[key] = fn.apply(<span class="hljs-built_in">this</span>, args)
     <span class="hljs-keyword">return</span> memo[key]
  }
}
</code></pre>
<p>We can apply this function to <code>getSquare</code> as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> memoGetSquare = memoize(getSquare, <span class="hljs-function"><span class="hljs-params">num</span> =&gt;</span> num)
</code></pre>
<p>Memoizing a function accepting multiple arguments:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getDivision = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a/b

<span class="hljs-comment">// memoizing using the helper</span>
<span class="hljs-keyword">const</span> memoGetDivision= memoize(getDivision, <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> <span class="hljs-string">`<span class="hljs-subst">${a}</span>_<span class="hljs-subst">${b}</span>`</span>)
</code></pre>
<h2 id="memoizing-async-functions">Memoizing async functions</h2>
<p>Let's say there' a function called <code>expensiveOperation(key)</code> which accepts a key as an argument and performs some async operation before returning the final result via a callback:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// does some async operation and invokes the callback with the final result</span>

expensiveOperation(key, <span class="hljs-function">(<span class="hljs-params"> data</span>) =&gt;</span> {
   <span class="hljs-comment">// Do something</span>
})
</code></pre>
<p>Let's use similar notion as above to memoize this function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> memo = {}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoExpensiveOperation</span>(<span class="hljs-params">key, callback</span>)</span>{
  <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)){
    callback(memo[key])
    <span class="hljs-keyword">return</span>
  } 

  expensiveOperation(key, <span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
   memo[key] = data
   callback(data)
  })
}
</code></pre>
<p>So that was pretty easy. But wait! It doesn't solve the whole problem yet. Consider the following scenario:</p>
<p>1- Invoked <code>expensiveOperation</code> with key 'a'</p>
<p>2- While #1 is still in progress, invoked it again with same key</p>
<p>The function would run twice for the same operation because #1 is yet to save the final data in <code>memo</code>. That's not something we wanted. We would instead want concurrent calls to be resolved at once after the earliest call is complete.</p>
<p>To address this issue we can track the operations currently in progress, say we do so by putting it in some sort of queue. Now, if we receive a call for an operation, while it's still in queue, we further enqueue the new call. This way we keep accumulating the repetitive calls and once the operation is done, all of these are processed in one go.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> memo = {}, progressQueues = {}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoExpensiveOperation</span>(<span class="hljs-params">key, callback</span>)</span>{
     <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)){
       callback(memo[key])
       <span class="hljs-keyword">return</span>
      }

     <span class="hljs-keyword">if</span>(!progressQueues.hasOwnProperty(key)){
        <span class="hljs-comment">// processing new key, create an entry for it in progressQueues</span>
        progressQueues[key] = [callback]

      } <span class="hljs-keyword">else</span> {
       <span class="hljs-comment">// processing a key that's already being processed, enqueue it's callback and exit. </span>
        progressQueues[key].push(callback);
        <span class="hljs-keyword">return</span>
      }

      expensiveOperation(key, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
           <span class="hljs-comment">// memoize result</span>
           memo[key] = data 
           <span class="hljs-comment">// process all the enqueued items after it's done</span>
           <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> callback <span class="hljs-keyword">of</span> progressQueues[key]) {
                callback(data)
           }
           <span class="hljs-comment">// clean up progressQueues</span>
           <span class="hljs-keyword">delete</span> progressQueue[key]
       })

}
</code></pre>
<p>We can go a step further, just like the last section, and create a re-usable helper say <code>memoizeAsync</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoizeAsync</span>(<span class="hljs-params">fn, getKey</span>)</span>{
   <span class="hljs-keyword">const</span> memo = {}, progressQueues = {}

   <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoized</span>(<span class="hljs-params">...allArgs</span>)</span>{
       <span class="hljs-keyword">const</span> callback = allArgs[allArgs.length<span class="hljs-number">-1</span>]
       <span class="hljs-keyword">const</span> args = allArgs.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>)
       <span class="hljs-keyword">const</span> key = getKey(...args)

        <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)){
            callback(key)
            <span class="hljs-keyword">return</span>
        }


        <span class="hljs-keyword">if</span>( !progressQueues.hasOwnProperty(key) ){
           <span class="hljs-comment">// processing new key, create an entry for it in progressQueues</span>
           progressQueues[key] = [callback]
        } <span class="hljs-keyword">else</span> {
           <span class="hljs-comment">// processing a key that's already being processed, enqueue it's callback and exit. </span>
           progressQueues[key].push(callback);
           <span class="hljs-keyword">return</span>
        }

        fn.call(<span class="hljs-built_in">this</span>, ...args , <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
           <span class="hljs-comment">// memoize result</span>
           memo[key] = data 
           <span class="hljs-comment">// process all the enqueued items after it's done</span>
           <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> callback <span class="hljs-keyword">of</span> progressQueues[key]) {
                callback(data)
           }
           <span class="hljs-comment">// clean up progressQueues</span>
           <span class="hljs-keyword">delete</span> progressQueue[key]
       })
   }
}

<span class="hljs-comment">// USAGE</span>

<span class="hljs-keyword">const</span> memoExpensiveOperation = memoizeAsync(expensiveOperation, <span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> key)
</code></pre>
<h2 id="promises">Promises</h2>
<p>Let's say we have a function <code>processData(key)</code> which accepts a key as argument and returns a Promise. Let's see how it can be memoized.</p>
<h3 id="memoizing-the-underlying-promise">Memoizing the underlying promise:</h3>
<p>Simplest way would be to memoize the promise issued against the key. Here's how it would look like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> memo = {}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoProcessData</span>(<span class="hljs-params">key</span>)</span>{
  <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)) {
    <span class="hljs-keyword">return</span> memo[key]
  }

  memo[key] = processData(key) <span class="hljs-comment">// memoize the promise for key</span>
  <span class="hljs-keyword">return</span> memo[key]
}
</code></pre>
<p>The code is fairly simple and self-explanatory here.  We can use the <code>memoize</code> helper we created a while ago:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> memoProcessData = memoize(processData, <span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> key)
</code></pre>
<h3 id="can-we-memoize-the-value-returned-by-promise">Can we memoize the value returned by Promise?</h3>
<p>Yes. We can apply the same approach as the callback here. Though it might be an overkill for the sake of memoizing such a function:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> memo = {},  progressQueues = {}

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">memoProcessData</span>(<span class="hljs-params">key</span>)</span>{

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
      <span class="hljs-comment">// if the operation has already been done before, simply resolve with that data and exit</span>
      <span class="hljs-keyword">if</span>(memo.hasOwnProperty(key)){
        resolve(memo[key])
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-keyword">if</span>( !progressQueues.hasOwnProperty(key) ){
        <span class="hljs-comment">// called for a new key, create an entry for it in progressQueues</span>
        progressQueues[key] = [[resolve, reject]]

      } <span class="hljs-keyword">else</span> {
       <span class="hljs-comment">// called for a key that's still being processed, enqueue it's handlers and exit.         </span>
        progressQueues[key].push([resolve, reject]);
        <span class="hljs-keyword">return</span>;
      }


      processData(key)
        .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
            memo[key] = data; <span class="hljs-comment">// memoize the returned data</span>
            <span class="hljs-comment">// process all the enqueued entries after successful operation</span>
            <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> [resolver, ] <span class="hljs-keyword">of</span> progressQueues[key])
              resolver(data)
        })
        .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
           <span class="hljs-comment">// process all the enqueued entries after failed operation</span>
           <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> [, rejector] <span class="hljs-keyword">of</span> progressQueues[key])
              rejector(error);
         })
        .finally(<span class="hljs-function">() =&gt;</span> {
          <span class="hljs-comment">// clean up progressQueues</span>
           <span class="hljs-keyword">delete</span> progressQueues[key]
         })
    })
  }
</code></pre>
<h2 id="further-improvement">Further improvement</h2>
<p>Since we're using a <code>memo</code> object to keep track of memoized operations, with too many calls to <code>expensiveOperation</code> with various keys(and each operation returning a sizeable chunk of data after processing) the size of this object may grow beyond what's ideal. To handle this scenario we can use a cache eviction policy such as <a target="_blank" href="https://en.wikipedia.org/wiki/LRU">LRU</a> (Least Recently Used). It would ensure we're memoizing without crossing memory limits!</p>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[Tree: efficient traversal with parent pointer]]></title><description><![CDATA[In the first part of this series we looked at recursive and iterative approaches for traversing through a binary tree.  If you haven't looked through it yet, I  highly recommend you to check it out first. I'll wait here, I promise ;)
In real life app...]]></description><link>https://stackfull.dev/tree-efficient-traversal-with-parent-pointer</link><guid isPermaLink="true">https://stackfull.dev/tree-efficient-traversal-with-parent-pointer</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[data structures]]></category><category><![CDATA[algorithms]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Sat, 28 Aug 2021 06:11:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630119950213/S9O3BrerE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a target="_blank" href="https://stackfull.dev/series/tree-javascript">first part of this series</a> we looked at recursive and iterative approaches for traversing through a binary tree.  If you haven't looked through it yet, I  highly recommend you to check it out first. I'll wait here, I promise ;)</p>
<p>In real life applications, it's quite common for tree nodes to have a parent field: a field which points to the parent node, hence also called as the parent pointer. Let's take the example of DOM in browser.  Say we select any node using the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> element = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#id"</span>)
</code></pre>
<p>Now, we would find <code>element.parentNode</code> to be pointing to the element's parent.</p>
<p>In this article, we'll look at how we can use these <code>parent</code> pointers to make the traversal more efficient. I'll explain what do I mean by 'more efficient' in a bit. In the next article, we'll also see how we can use the lessons learnt here to create <code>myQuery</code> library (a lightweight <code>jQuery</code> clone) from scratch.</p>
<h2 id="updating-our-node-definition">Updating our <code>Node</code> definition:</h2>
<p>First off, we need to update our <code>Node</code> function  (side-note: in OOPs world you may call this a <code>class</code> instead, because this function is always to be invoked with the <code>new</code> operator):</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Node</span>(<span class="hljs-params">value</span>)</span>{
  <span class="hljs-built_in">this</span>.value = value
  <span class="hljs-built_in">this</span>.left = <span class="hljs-literal">null</span>
  <span class="hljs-built_in">this</span>.right = <span class="hljs-literal">null</span>
  <span class="hljs-built_in">this</span>.parent = <span class="hljs-literal">null</span> <span class="hljs-comment">// added parent field</span>
}
</code></pre>
<p>Nothing fancy here!  Now let's see how we can use this new <code>Node</code> definition to create  a similar tree, as we did in last article.</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">const</span> root = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">2</span>)

<span class="hljs-keyword">const</span> left = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">1</span>)
root.left = left
left.parent = root

<span class="hljs-keyword">const</span> right = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">3</span>)
root.right = right
right.parent = root
</code></pre>
<p>Alright so that was simple too. We simply needed to ensure <code>parent</code> fields point to the parent node. Here's a visual reference for the final tree we get using the code above: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630116404318/FzFoTp0y5.png" alt="Screenshot 2021-08-28 at 7.36.28 AM.png" /></p>
<h2 id="finding-the-successor">Finding the successor</h2>
<h3 id="preorder-successor">PreOrder successor</h3>
<p>Let's do something more fun. How about finding the next node in <code>preOrder</code> traversal of tree given the current node and the fact that each node has a <code>parent</code> pointer. Let me rephrase this question for clarity:</p>
<blockquote>
<p>How can be find out the preOrder successor of any node in a binary tree? Assume that each node has a <code>parent</code> pointer.</p>
</blockquote>
<p>Let's try to dissect this problem. </p>
<ol>
<li>First off, we're dealing with preOrder here, that means we're looking for following order:<pre><code>root -&gt; <span class="hljs-attribute">left</span> -&gt; <span class="hljs-attribute">right</span>
</code></pre></li>
<li>That means if we're already at current node, we want to look for the left child node as successor. </li>
<li>What if there's no left child at all ? Well in that case, we look for the right child and if it's there, that's the successor.</li>
<li>If there's no left or right child, then we need to backtrack (keep going upwards towards the parent). We keep backtracking <strong>till parent is being reached via it's right child</strong> (because that means preOrder is complete for whole subtree under the parent, by definition on #1).</li>
</ol>
<p>So here's what the final algorithm would look like:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">preOrderSuccessor</span>(<span class="hljs-params">node</span>)</span>{
   <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

   <span class="hljs-keyword">if</span>(node.left) <span class="hljs-keyword">return</span> node.left
   <span class="hljs-keyword">if</span>(node.right) <span class="hljs-keyword">return</span> node.right

   <span class="hljs-keyword">let</span> parent = node.parent

   <span class="hljs-keyword">while</span>(parent &amp;&amp; parent.right === node) {
     node = node.parent
     parent = parent.parent
   }

   <span class="hljs-keyword">if</span>(!parent) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span> <span class="hljs-comment">// we backtracked till root, so no successor</span>

   <span class="hljs-keyword">return</span> parent.right
}
</code></pre>
<p>Here's  the visual cue for better understanding.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630121945520/GQOxqsVuU.png" alt="Screenshot 2021-08-28 at 9.08.26 AM.png" /></p>
<p>Here's a <a target="_blank" href="https://gist.github.com/anish000kumar/2bd0d9932bef066e7c72a18e8814b0c2">link to a gist</a> on this idea, in case you want to explore it for yourself.</p>
<h3 id="inorder-successor">InOrder successor</h3>
<p>Finding InOrder successor is pretty similar. Let's go step by step:</p>
<ol>
<li>For InOrder successor we are looking to traverse in following way:<pre><code><span class="hljs-attribute">left</span> -&gt; root -&gt; <span class="hljs-attribute">right</span>
</code></pre></li>
<li><p>If we're at current node, and there's anything on it's right then we can get the successor by finding the leftmost node on the right subtree.</p>
</li>
<li><p>If there's no right child, then we need to backtrack (move upwards). We keep moving upwards till <strong>parent is reached via it's right child</strong>, because that means whole subtree has been traversed already (by definition in #1). </p>
</li>
<li><p>Once we find the nearest parent, which has been found via it's left child, this it is returned as the successor. Why? Because it means it's a node whose left tree has been explored, so by definition in #1, the node itself is now the successor.</p>
</li>
</ol>
<p>Here's the final algorithm:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">inOrderSuccessor</span>(<span class="hljs-params">node</span>)</span>{
   <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

   <span class="hljs-keyword">if</span>(node.right){
     <span class="hljs-keyword">let</span> current = node.right
     <span class="hljs-keyword">while</span>(current &amp;&amp; current.left) current = current.left
     <span class="hljs-keyword">return</span> current
   }

   <span class="hljs-keyword">let</span> parent = node.parent

   <span class="hljs-keyword">while</span>(parent &amp;&amp; parent.right === node) {
     root = node.parent
     parent = parent.parent
   }

   <span class="hljs-keyword">if</span>(!parent) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>

   <span class="hljs-keyword">return</span> parent
}
</code></pre>
<p>Visual cue:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630125933639/Zw-NhbXIX.png" alt="Screenshot 2021-08-28 at 10.14.58 AM.png" /></p>
<p><a target="_blank" href="https://gist.github.com/anish000kumar/169899323d4b651651408b711beb21f6">Link to gist</a> on this idea.</p>
<h3 id="postorder-successor">PostOrder successor</h3>
<p>Let's follow similar thought process for finding the postOrder successor:</p>
<ol>
<li>For postOrder, we are looking to traverse in following way:<pre><code><span class="hljs-attribute">left</span> -&gt; <span class="hljs-attribute">right</span> -&gt; root
</code></pre></li>
<li><p>So, if we're at any node it means it's left and right subtree has already been explored. That means we need to look at the parent for successor.</p>
</li>
<li><p>If we're reaching the parent from it's right child, that means parent itself is successor, by the definition in #1</p>
</li>
<li><p>If we're reaching the parent from it's left child, that means  parent's right child is to be explored next (as per definition in #1). So now we need to simply return the leftmost node in parent's right child as successor.</p>
</li>
</ol>
<p>Here's the final algorithm:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">postOrderSuccessor</span>(<span class="hljs-params">node</span>)</span>{
   <span class="hljs-keyword">if</span>(!node) <span class="hljs-keyword">return</span>

   <span class="hljs-keyword">let</span> parent = node.parent
   <span class="hljs-keyword">if</span>(!parent) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>

   <span class="hljs-keyword">if</span>(parent.right === node). return parent

   <span class="hljs-keyword">let</span> current = parent.right
   <span class="hljs-keyword">while</span>(current &amp;&amp; (current.left || current.right)){
     current = (current.left || current.right)
   }

   <span class="hljs-keyword">return</span> current
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630129446688/K8EtBM7a-f.png" alt="Screenshot 2021-08-28 at 11.13.50 AM.png" /></p>
<p><a target="_blank" href="https://gist.github.com/anish000kumar/7927c87003026b313eee3843181bb780">Link to gist</a> to play around with this idea.</p>
<h2 id="using-successor-algorithms-for-better-traversal">Using successor algorithms for better traversal</h2>
<h3 id="why">Why ?</h3>
<p>Why do we need to use <code>parent</code> field to come up with a traversal algorithm at all? It's a valid question, since we've already come up with recursive and iterative approaches to traverse the tree, that too without the need for <code>parent</code> field.</p>
<p>The reason why we're doing this is because of added space complexity in our previous approaches. If you remember we needed to use one or two stacks (depending on traversal method) in the previous article, to get any of the traversal algorithms working. Even in recursive approach, though we're not directly using a stack but recursion itself is based on call-stacks, so there's hidden in-memory stack being used there as well.  The problem is that size of this stack is going to increase with depth of our tree, hence it's not the best solution since we've a way to do the same task while spending lesser space . By using the <code>parent</code> pointer we can get rid of those stacks completely, saving us significant space i.e. going from space complexity of O(logN) where N denotes size of a balanced tree to O(1). Let's see how.</p>
<h2 id="preorder-traversal">PreOrder traversal</h2>
<p>For preOrder traversal, we start at the <code>root</code> of the tree. Afterwards, we can keep fetching the preOrder successor using the algorithm above to traverse the whole tree:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">preOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-comment">// first node</span>
  <span class="hljs-built_in">console</span>.log(root.value);

  <span class="hljs-keyword">let</span> current = root
  <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){
    <span class="hljs-keyword">const</span> next = preOrderSuccessor(current)
    <span class="hljs-keyword">if</span>(!next) <span class="hljs-keyword">break</span>

    <span class="hljs-comment">// do something</span>
    <span class="hljs-built_in">console</span>.log(next.value)

    current = next
  }
}
</code></pre>
<h2 id="inorder-traversal">InOrder traversal</h2>
<p>For InOrder traversal, starting node would be the left-most node of the tree. Thereafter we can keep fetching the successor using the algorithm above to traverse the whole tree:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">inOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-comment">// start at the left most node</span>
  <span class="hljs-keyword">while</span>(root &amp;&amp; root.left){
    root = root.left
  }

  <span class="hljs-comment">// first node</span>
  <span class="hljs-built_in">console</span>.log(root.value);

  <span class="hljs-keyword">let</span> current = node
  <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){
    <span class="hljs-keyword">const</span> next = inOrderSuccessor(current)
    <span class="hljs-keyword">if</span>(!next) <span class="hljs-keyword">break</span>

    <span class="hljs-comment">// do something</span>
    <span class="hljs-built_in">console</span>.log(current.value)

    current = next
  }
}
</code></pre>
<h2 id="postorder-traversal">PostOrder traversal</h2>
<p>Very similar to InOrder approach above:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">postOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-comment">// start at the left most node</span>
  <span class="hljs-keyword">while</span>(root &amp;&amp; root.left){
    root = root.left
  }

  <span class="hljs-comment">// first node</span>
  <span class="hljs-built_in">console</span>.log(root.value);

  <span class="hljs-keyword">let</span> current = node
  <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){
    <span class="hljs-keyword">const</span> next = postOrderSuccessor(current)
    <span class="hljs-keyword">if</span>(!next) <span class="hljs-keyword">break</span>

    <span class="hljs-comment">// do something</span>
    <span class="hljs-built_in">console</span>.log(current.value)

    current = next
  }
}
</code></pre>
<h2 id="quick-exercise">Quick exercise</h2>
<p>Can you come up with algorithms for finding predecessor (inOrder, preOrder and postOrder) if each node has a parent pointer ? It would be a fun exercise. Try it out and let me know in the comments.</p>
<div class="hn-embed-widget" id="message"></div>]]></content:encoded></item><item><title><![CDATA[Tree data structure in JavaScript]]></title><description><![CDATA[Tree is an interesting data structure. It has wide variety of applications in all sorts of fields. For example:

DOM is a tree data structure

Directory and files in our OS can be represented as trees

A family hierarchy can be represented as a tree....]]></description><link>https://stackfull.dev/tree-data-structure-in-javascript</link><guid isPermaLink="true">https://stackfull.dev/tree-data-structure-in-javascript</guid><category><![CDATA[data structures]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Anish Kumar]]></dc:creator><pubDate>Fri, 27 Aug 2021 06:20:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630045094854/RzXIvyhBb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tree is an interesting data structure. It has wide variety of applications in all sorts of fields. For example:</p>
<ul>
<li><p>DOM is a tree data structure</p>
</li>
<li><p>Directory and files in our OS can be represented as trees</p>
</li>
<li><p>A family hierarchy can be represented as a tree.</p>
</li>
</ul>
<p>There are bunch of variations of tree (such as heaps, BST etc.) which can be used in solving problems related to scheduling, image processing, databases etc. Many of complex problems may not seem related to tree on a quick look, but can actually be represented as one. We'll walk through such problems as well (in later parts of this series) to see how trees can make seemingly complex problems much easier to comprehend and solve.</p>
<p>Don't forget to subscribe to my newsletter (subscription form should be at the top of this article) if you'd like to be informed about further posts in this series.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Implementing a <code>Node</code> for a binary tree is pretty straightforward.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Node</span>(<span class="hljs-params">value</span>)</span>{
  <span class="hljs-built_in">this</span>.value = value
  <span class="hljs-built_in">this</span>.left = <span class="hljs-literal">null</span>
  <span class="hljs-built_in">this</span>.right = <span class="hljs-literal">null</span>
}
<span class="hljs-comment">// usage</span>
<span class="hljs-keyword">const</span> root = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">2</span>)
root.left = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">1</span>)
root.right = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">3</span>)
</code></pre>
<p>So these few lines of code would create a binary tree for us which looks like this:</p>
<pre><code class="lang-javascript">           <span class="hljs-number">2</span>  
        /      \
       /         \
     <span class="hljs-number">1</span>            <span class="hljs-number">3</span>
   /   \        /    \
<span class="hljs-literal">null</span>  <span class="hljs-literal">null</span>   <span class="hljs-literal">null</span>   <span class="hljs-literal">null</span>
</code></pre>
<p>Cool! So that was easy. Now, how do we put this to use?</p>
<h2 id="heading-traversal">Traversal</h2>
<p>Let's start with trying to walk through these connected tree nodes (or a tree). Just as we can iterate through an array, it would be cool if we can 'iterate' through tree nodes as well. However, trees are not linear data structures like arrays, so there isn't just one way of traversing these. We can broadly classify the traversal approaches into following:</p>
<ul>
<li><p>Breadth first traversal</p>
</li>
<li><p>Depth first traversal</p>
</li>
</ul>
<h2 id="heading-breadth-first-searchtraversal-bfs">Breadth First Search/Traversal (BFS)</h2>
<p>In this approach, we traverse the tree level by level. We would start at the root, then cover all of it's children, and we cover all of 2nd level children, so on and so forth. For example for the tree above, traversal would result in something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>
</code></pre>
<p>Here's an illustration with slightly complex tree to make this even simpler to understand:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066197622/MEa_jdswt.png" alt="BFS.png" /></p>
<p>To achieve this form of traversal we can use a queue (First In First Out) data structure. Here's how the overall algorithm would look like:</p>
<ol>
<li><p>Initiate a queue with root in it</p>
</li>
<li><p>Remove the first item out of queue</p>
</li>
<li><p>Push the left and right children of popped item into the queue</p>
</li>
<li><p>Repeat steps 2 and 3 until the queue is empty</p>
</li>
</ol>
<p>Here's how this algorithm would look like post implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkBFS</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> queue = [root]
  <span class="hljs-keyword">while</span>(queue.length){
      <span class="hljs-keyword">const</span> item = queue.shift()
      <span class="hljs-comment">// do something</span>
      <span class="hljs-built_in">console</span>.log(item)

      <span class="hljs-keyword">if</span>(item.left) queue.push(item.left)
      <span class="hljs-keyword">if</span>(item.right) queue.push(item.right)
   }
}
</code></pre>
<p>We can modify above algorithm slightly to return an array of arrays, where each inner array represents a level with elements within in:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkBFS</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> queue = [root], ans = []

  <span class="hljs-keyword">while</span>(queue.length){
      <span class="hljs-keyword">const</span> len = queue.length, level = []
      <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; len; i++){
          <span class="hljs-keyword">const</span> item = queue.shift()
          level.push(item)
          <span class="hljs-keyword">if</span>(item.left) queue.push(item.left)
          <span class="hljs-keyword">if</span>(item.right) queue.push(item.right)
       }
       ans.push(level)
   }
  <span class="hljs-keyword">return</span> ans
}
</code></pre>
<h2 id="heading-depth-first-searchtraversal-dfs">Depth First Search/Traversal (DFS)</h2>
<p>In DFS, we take one node and keep exploring it's children until the depth the fully exhausted. It can be done in one of following ways:</p>
<pre><code class="lang-javascript"> root node -&gt; left node -&gt; right node <span class="hljs-comment">// pre-order traversal</span>
 left node -&gt; root node -&gt; right node <span class="hljs-comment">// in-order traversal</span>
 left node -&gt; right node -&gt; root node <span class="hljs-comment">// post-order traversal</span>
</code></pre>
<p>All of these traversal techniques can be implemented recursively as well as iteratively. Let's jump into the implementation details:</p>
<h3 id="heading-pre-order-traversal">Pre-Order traversal</h3>
<p>Here's how PreOrder traversal looks like for a tree:</p>
<pre><code class="lang-javascript"> root node -&gt; left node -&gt; right node
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066335323/uu_rnMwc2.png" alt="PreOrder visual.png" /></p>
<h4 id="heading-trick">Trick:</h4>
<p>We can use this simple trick to find out the PreOrder traversal of any tree manually: traverse the entire tree starting from the root node keeping yourself to the left.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066309451/tKaff2RAo0.png" alt="preOrderTrick.png" /></p>
<h4 id="heading-implementation">Implementation:</h4>
<p>Let's dive into actual implementation for such a traversal. <strong>Recursive approach</strong> is fairly intuitive.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkPreOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-comment">// do something here</span>
  <span class="hljs-built_in">console</span>.log(root.val)

  <span class="hljs-comment">// recurse through child nodes</span>
  <span class="hljs-keyword">if</span>(root.left) walkPreOrder(root.left)
  <span class="hljs-keyword">if</span>(root.right) walkPreOrder(root.right)
}
</code></pre>
<p><strong>Iterative approach</strong> for PreOrder traversal is very similar to BFS, except we use a <code>stack</code> instead of a <code>queue</code> and we push the right child first into the stack:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkPreOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> stack = [root]
  <span class="hljs-keyword">while</span>(stack.length){
      <span class="hljs-keyword">const</span> item = stack.pop()

      <span class="hljs-comment">// do something</span>
      <span class="hljs-built_in">console</span>.log(item)

      <span class="hljs-comment">// Left child is pushed after right one, since we want to print left child first hence it must be above right child in the stack</span>
      <span class="hljs-keyword">if</span>(item.right) stack.push(item.right)
      <span class="hljs-keyword">if</span>(item.left) stack.push(item.left)
   }
}
</code></pre>
<h3 id="heading-in-order-traversal">In-Order traversal</h3>
<p>Here's how InOrder traversal looks like for a tree:</p>
<pre><code class="lang-javascript">left node -&gt; root node -&gt; right node
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066398214/_S82oVUdj.png" alt="InOrder visual.png" /></p>
<h4 id="heading-trick-1">Trick:</h4>
<p>We can use this simple trick to find out InOrder traversal of any tree manually: keep a plane mirror horizontally at the bottom of the tree and take the projection of all the nodes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066383550/7fxAFVhV1.png" alt="Inorder trick.png" /></p>
<h4 id="heading-implementation-1">Implementation:</h4>
<p><strong>Recursive:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkInOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">if</span>(root.left) walkInOrder(root.left)

 <span class="hljs-comment">// do something here</span>
  <span class="hljs-built_in">console</span>.log(root.val)

  <span class="hljs-keyword">if</span>(root.right) walkInOrder(root.right)
}
</code></pre>
<p><strong>Iterative:</strong> This algorithm may seem a bit cryptic at first. But it's fairly intuitive. Let's look at it this way: in InOrder traversal left most child is printed first, then root and then right children. So first thought would be to come up with something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> curr = root

<span class="hljs-keyword">while</span>(curr){
  <span class="hljs-keyword">while</span>(curr.left){
    curr = curr.left <span class="hljs-comment">// get to leftmost child</span>
  }

  <span class="hljs-built_in">console</span>.log(curr) <span class="hljs-comment">// print it</span>

  curr = curr.right <span class="hljs-comment">// now move to right child</span>
}
</code></pre>
<p>In the above approach we're not able to backtrack however i.e. go back to parent nodes which led to left most nodes. So we'll need a stack to record those. Hence our revised approach may look like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stack = []
<span class="hljs-keyword">const</span> curr = root

<span class="hljs-keyword">while</span>(stack.length || curr){
  <span class="hljs-keyword">while</span>(curr){
    stack.push(curr) <span class="hljs-comment">// keep recording the trail, to backtrack</span>
    curr = curr.left <span class="hljs-comment">// get to leftmost child</span>
  }
  <span class="hljs-keyword">const</span> leftMost = stack.pop()
  <span class="hljs-built_in">console</span>.log(leftMost) <span class="hljs-comment">// print it</span>

  curr = leftMost.right <span class="hljs-comment">// now move to right child</span>
}
</code></pre>
<p>Now we can use the above approach to lay down the final iterative algorithm:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkInOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> stack = []
  <span class="hljs-keyword">let</span> current = root

  <span class="hljs-keyword">while</span>(stack.length || current){
      <span class="hljs-keyword">while</span>(current){
         stack.push(current)
         current = current.left
      }
      <span class="hljs-keyword">const</span> last = stack.pop()

      <span class="hljs-comment">// do something</span>
      <span class="hljs-built_in">console</span>.log(last)

      current = last.right
   }
}
</code></pre>
<h3 id="heading-post-order-traversal">Post-Order traversal</h3>
<p>Here's how postOrder traversal looks like for a tree:</p>
<pre><code class="lang-javascript"> left node -&gt; right node -&gt; root node
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066468275/aXvp4kZ-V.png" alt="PostOrder visual.png" /></p>
<h4 id="heading-trick-2">Trick:</h4>
<p>For quick manual PostOrder traversal of any tree: pluck all the leftmost leaf nodes one by one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630066456516/oWu_cm681.png" alt="PostOrder trick.png" /></p>
<h4 id="heading-implementation-2">Implementation:</h4>
<p>Let's dive into actual implementation for such a traversal.</p>
<p><strong>Recursive:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkPostOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">if</span>(root.left) walkPostOrder(root.left)
  <span class="hljs-keyword">if</span>(root.right) walkPostOrder(root.right)

  <span class="hljs-comment">// do something here</span>
  <span class="hljs-built_in">console</span>.log(root.val)

}
</code></pre>
<p><strong>Iterative:</strong> We already have iterative algorithm for preOrder traversal. Can we use that? Since PostOrder traversal seems to be just reverse of PreOrder traversal. Let's see:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// PreOrder:</span>
root -&gt; left -&gt; right

<span class="hljs-comment">// Reverse of PreOrder:</span>
right -&gt; left -&gt; root

<span class="hljs-comment">// But PostOrder is:</span>
left -&gt; right -&gt; root
</code></pre>
<p>Ah! So there's a slight difference. But we can accomodate that by modifying our PreOrder algorithm slightly and then reversing it should give the PostOrder results. Overall algorithm would be:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// record result using </span>
root -&gt; right -&gt; left

<span class="hljs-comment">// reverse result</span>
left -&gt; right -&gt; root
</code></pre>
<ul>
<li><p>Use a similar approach to the iterative preOrder algorithm above, using a temporary <code>stack</code>.</p>
<ul>
<li>Only exception is we go <code>root -&gt; right -&gt; left</code> instead of <code>root -&gt; left -&gt; right</code></li>
</ul>
</li>
<li><p>Keep recording the traversal sequence in an array<code>result</code></p>
</li>
<li><p>Reversal of <code>result</code> gives postOrder traversal</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">walkPostOrder</span>(<span class="hljs-params">root</span>)</span>{
  <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> []

  <span class="hljs-keyword">const</span> tempStack = [root], result = []

  <span class="hljs-keyword">while</span>(tempStack.length){
      <span class="hljs-keyword">const</span> last = tempStack.pop()

      result.push(last)

      <span class="hljs-keyword">if</span>(last.left) tempStack.push(last.left)
      <span class="hljs-keyword">if</span>(last.right) tempStack.push(last.right)
    }

    <span class="hljs-keyword">return</span> result.reverse()
}
</code></pre>
<h3 id="heading-bonus-javascript-tip">Bonus: JavaScript tip</h3>
<p>How nice it would be if we could traverse the tree in the following way:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> node <span class="hljs-keyword">of</span> walkPreOrder(tree) ){
   <span class="hljs-built_in">console</span>.log(node)
 }
</code></pre>
<p>Looks really nice and pretty simple to read, isn't it? All we've got to do is use a <code>walk</code> function, which would return an iterator.</p>
<p>Here's how we can modify our <code>walkPreOrder</code> function above to behave as per the example shared above:</p>
<pre><code class="lang-javascript">
<span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">walkPreOrder</span>(<span class="hljs-params">root</span>)</span>{
   <span class="hljs-keyword">if</span>(root === <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>

  <span class="hljs-keyword">const</span> stack = [root]
  <span class="hljs-keyword">while</span>(stack.length){
      <span class="hljs-keyword">const</span> item = stack.pop()
      <span class="hljs-keyword">yield</span> item
      <span class="hljs-keyword">if</span>(item.right) stack.push(item.right)
      <span class="hljs-keyword">if</span>(item.left) stack.push(item.left)
   }
}
</code></pre>
]]></content:encoded></item></channel></rss>