<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Trees - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Trees - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 26 Aug 2026 13:30:03 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/trees/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Coding Interview Tree Traversal Crash Course – The Only One You'll Ever Need ]]>
                </title>
                <description>
                    <![CDATA[ Are you preparing for coding interviews? I designed a crash course series to help you out. I'm Lynn, a software engineer and a recent graduate from the University of Chicago. This is the second course in my Coding Interview Crash Course Series. Feel ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/coding-interview-tree-traversal-crash-course-the-only-one-youll-ever-need/</link>
                <guid isPermaLink="false">66d4601755db48792eed3f73</guid>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ interview questions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interview tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lynn Zheng ]]>
                </dc:creator>
                <pubDate>Mon, 16 Aug 2021 23:49:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/tree-thumb.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you preparing for coding interviews? I designed a crash course series to help you out.</p>
<p>I'm Lynn, a software engineer and a recent graduate from the University of Chicago. This is the second course in my Coding Interview Crash Course Series. Feel free to check out <a target="_blank" href="https://www.youtube.com/channel/UCZ2MeG5jTIqgzEMiByrIzsw">my YouTube channel, Lynn's DevLab</a>, to stay updated on this series.</p>
<p>This crash course is about Tree Traversal. If you just want to dive right in, <a target="_blank" href="https://youtu.be/uaeCfsCcYWo">you can find the course here</a> (and linked at the bottom of this article). If you want a little more info, read on. 😎</p>
<h2 id="heading-who-is-the-course-for-and-what-are-tree-traversal-algorithms">Who is the Course for and What are Tree Traversal Algorithms? 🌳</h2>
<p>You will get the most of this course if you already know a bit about the <strong>Tree</strong> data structure. Check out <a target="_blank" href="https://www.freecodecamp.org/news/binary-data-structures-an-intro-to-trees-and-heaps-in-javascript-962ab536cb42/">these</a> <a target="_blank" href="https://www.freecodecamp.org/news/the-codeless-guide-to-tree-data-structures/">tutorials</a> if you need a refresher.</p>
<p>We will cover the traversal algorithms for both <strong>Binary Trees</strong> and <strong>N-ary Trees</strong> (in which each parent node has an arbitrary number of children).</p>
<p>If you have heard about Binary Search Trees (BST) before, that's a special type of Binary Tree so the techniques we are going to learn here also apply.</p>
<p>Trees are a favorite interview subject among top tech companies like Google, Microsoft, and Facebook, so let's crunch this topic!</p>
<p>We will learn about four traversal techniques and solve their corresponding LeetCode problems hands-on.</p>
<p>The four techniques are:</p>
<ul>
<li><p><strong>Pre-order (Depth-First Search, DFS)</strong></p>
</li>
<li><p><strong>Post-order</strong></p>
</li>
<li><p><strong>In-order</strong></p>
</li>
<li><p><strong>Level-order (Breadth-First Search, BFS).</strong></p>
</li>
</ul>
<h2 id="heading-course-outline">Course Outline</h2>
<p>This course video runs for a total of 30 minutes and features:</p>
<ul>
<li><p>A high-level description of the four traversal techniques: <strong>pre-order, post-order, in-order, and level-order</strong></p>
</li>
<li><p><strong>Recursive</strong> implementations of pre-order, post-order, and in-order (Note: this doesn't apply to level-order)</p>
</li>
<li><p><strong>Iterative</strong> implementations of pre-order, post-order, in-order, and level-order</p>
</li>
<li><p>An extension of the templates from <strong>Binary Trees</strong> to <strong>N-ary Trees</strong></p>
</li>
</ul>
<p>Let's dive into each of the four techniques below.</p>
<h2 id="heading-tree-traversal-demonstration-using-an-example-tree">Tree Traversal Demonstration Using an Example Tree</h2>
<p>We will use the following tree to demonstrate the output from the four traversal techniques.</p>
<p>Note that this tree is a simple Binary Tree, not a Binary Search Tree (BST). A BST is a special type of Binary Tree, so our techniques also apply. Also, <strong>in-order traversal</strong> becomes especially interesting when we work with a BST, as we will see below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screen-Shot-2021-08-16-at-2.48.44-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>An example Binary Tree. Note that it's not a Binary Search Tree (BST).</em></p>
<p>Given this tree, the traversal result from the four techniques are as follows:</p>
<ul>
<li><p>Pre-order: 1, 2, 4, 5, 3</p>
</li>
<li><p>Post-order: 4, 5, 2, 3, 1</p>
</li>
<li><p>In-order: 4, 2, 5, 1, 3</p>
</li>
<li><p>Level-order: 1, 2, 3, 4, 5</p>
</li>
</ul>
<h3 id="heading-pre-order-traversal">Pre-order Traversal</h3>
<p>Pre-order traversal is also known as <strong>Depth-First Search (DFS)</strong> if we analyze the tree as a graph and take the tree root node as our starting node in the search.</p>
<p>As in the example above, we go all the way down to the <strong>leftmost</strong> node before visiting any other node that is a left child of some parent node.</p>
<p>Pre-order traversal allows us to explore roots before leaves, and is hence ideal for tasks like copying a tree.</p>
<h3 id="heading-post-order-traversal">Post-order Traversal</h3>
<p>Post-order traversal does the opposite of pre-order traversal, allowing us to explore leaves before roots.</p>
<h3 id="heading-in-order-traversal">In-order Traversal</h3>
<p>In-order traversal is especially useful for flattening a tree into an array representation.</p>
<p>For a Binary Search Tree like below, in-order traversal outputs an array in a sorted, non-decreasing order: -4, 3, 2, 5, 18.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Screen-Shot-2021-08-16-at-2.51.44-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Binary Search Tree example</em></p>
<h3 id="heading-level-order-traversal">Level-order Traversal</h3>
<p>Level-order traversal is also known as <strong>Breadth-First Search (BFS)</strong> if we consider the tree as a graph and start our search from the tree root node.</p>
<p>We visit every node on the current level (depth) before moving onto those on the next level. Effectively, we visit the immediate neighbor of (one step away from) our current node before visiting neighbors that are farther away.</p>
<h2 id="heading-how-to-implement-these-four-techniques">How to Implement these Four Techniques</h2>
<p>We will use the following definition for a node of a Binary Tree:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Definition for a binary tree node.</span>
<span class="hljs-comment"># class TreeNode:</span>
<span class="hljs-comment">#     def __init__(self, val=0, left=None, right=None):</span>
<span class="hljs-comment">#         self.val = val</span>
<span class="hljs-comment">#         self.left = left</span>
<span class="hljs-comment">#         self.right = right</span>
</code></pre>
<h3 id="heading-recursive-implementation">Recursive implementation</h3>
<p>Recursive implementations are the most straightforward. The most important thing to remember is the order in which we concatenate the results from the two recursive calls (one on the left subtree and one on the right subtree) with the value of the current node.</p>
<pre><code class="lang-pgsql">def preorder(root):
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    <span class="hljs-keyword">return</span> [root.val] + preorder(root.left) + preorder(root.right)
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">postorder</span>(<span class="hljs-params">root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    <span class="hljs-keyword">return</span> postorder(root.left) + postorder(root.right) + [root.val]
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inorder</span>(<span class="hljs-params">root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    <span class="hljs-keyword">return</span> inorder(root.left) + [root.val] + inorder(root.right)
</code></pre>
<h3 id="heading-iterative-implementation">Iterative implementation</h3>
<p>Compared to recursive implementations, iterative implementations are non-trivial. Most require that we use either a stack or a queue to keep track of the nodes that we need to visit.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    ret = []
    stack = [root]
    <span class="hljs-keyword">while</span> stack:
        node = stack.pop()
        ret.append(node.val)
        <span class="hljs-comment"># note that we append the right child before the left child</span>
        <span class="hljs-keyword">if</span> node.right:
            stack.append(node.right)
        <span class="hljs-keyword">if</span> node.left:
            stack.append(node.left)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">postorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    <span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
    ret = deque()
    stack = [root]
    <span class="hljs-keyword">while</span> stack:
        node = stack.pop()
        ret.appendleft(node.val)
        <span class="hljs-keyword">if</span> node.left:
            stack.append(node.left)
        <span class="hljs-keyword">if</span> node.right:
            stack.append(node.right)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<p>The implementation for in-order traversal looks quite different from pre-order and post-order:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    ret = []
    stack = []
    <span class="hljs-keyword">while</span> root <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">or</span> stack:
        <span class="hljs-keyword">while</span> root <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
            stack.append(root)
            root = root.left
        root = stack.pop()
        ret.append(root.val)
        root = root.right
    <span class="hljs-keyword">return</span> ret
</code></pre>
<p>Lastly, we have level-order traversal, where we will output the result as <code>[[nodes on the first level], [nodes on the second level], [nodes on the third level], ...]</code>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">levelorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    ret = []
    <span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
    queue = deque([root])
    <span class="hljs-keyword">while</span> queue:
        ret_row = []
        <span class="hljs-comment"># fixed size for current level</span>
        <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(len(queue)):
            node = queue.popleft()
            ret_row.append(node.val)
            <span class="hljs-keyword">if</span> node.left:
                queue.append(node.left)
            <span class="hljs-keyword">if</span> node.right:
                queue.append(node.right)
        ret.append(ret_row)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<h3 id="heading-n-ary-trees">N-ary Trees</h3>
<p>We now extend our templates from handling Binary Trees to handling N-ary Trees. We use the following definition for the node of an N-ary Tree:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, val=None, children=[]</span>):</span>
        self.val = val
        self.children = children
</code></pre>
<p>To extend our iterative implementations to handle N-ary Trees, all we need to do is to make sure that we are appending the child nodes that we will visit in a correct order.</p>
<p>Recall that in pre-order traversal, we appended the right child before the left child. So when appending the children of a node of an N-ary Tree, we need to reverse the list of children.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    ret = []
    stack = [root]
    <span class="hljs-keyword">while</span> stack:
        node = stack.pop()
        ret.append(node.val)
        <span class="hljs-comment"># reverse the list of children</span>
        <span class="hljs-keyword">for</span> child <span class="hljs-keyword">in</span> node.children[::<span class="hljs-number">-1</span>]:
            stack.append(child)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<p>For the other traversal techniques, since we are appending the children from the left to the right, we can iterative over the list of children normally:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">postorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    <span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
    ret = deque()
    stack = [root]
    <span class="hljs-keyword">while</span> stack:
        node = stack.pop()
        ret.appendleft(node.val)
        <span class="hljs-keyword">for</span> child <span class="hljs-keyword">in</span> node.children:
            stack.append(child)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">levelorder</span>(<span class="hljs-params">self, root</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
        <span class="hljs-keyword">return</span> []
    ret = []
    <span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
    queue = deque([root])
    <span class="hljs-keyword">while</span> queue:
        ret_row = []
        <span class="hljs-comment"># fixed size for current level</span>
        <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(len(queue)):
            node = queue.popleft()
            ret_row.append(node.val)
            <span class="hljs-keyword">for</span> child <span class="hljs-keyword">in</span> node.children:
                queue.append(child)
        ret.append(ret_row)
    <span class="hljs-keyword">return</span> ret
</code></pre>
<p>And now we can apply our tree traversal templates to trees that have an arbitrary number of children at each node.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this crash course on tree traversal, we learned four techniques: pre-order, post-order, in-order, and level-order. We discussed how they differ and what tasks they are best for.</p>
<p>We also implemented them both in a recursive fashion and in an iterative one. Last but not least, we extended the techniques to deal with not only Binary Trees, but N-ary Trees.</p>
<p>I hope now you feel more confident about tree traversal interview questions. This is also a nice segue into the topic of my next crash course on graph traversal.</p>
<p>With the knowledge of pre-order traversal and level-order traversal, DFS and BFS won't be completely out of the blue for you 🤓 I will even talk about how I applied graph traversal when developing an algorithm for <a target="_blank" href="https://github.com/RuolinZheng08/unity-clicky-galaxy">my match-three game, Clicky Galaxy,</a> so stay tuned!</p>
<h2 id="heading-resources">Resources</h2>
<p>Watch the course here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/uaeCfsCcYWo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>Access the code template on my GitHub:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="f6e55b09eb096fe5fe630249cd859b07">
        <script src="https://gist.github.com/RuolinZheng08/f6e55b09eb096fe5fe630249cd859b07.js"></script></div><p> </p>
<p>Check out the whole crash course series:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/undefined" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>And lastly, feel free to subscribe to my YouTube channel for more content like this :)</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/undefined" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Random Forest Classifier Tutorial: How to Use Tree-Based Algorithms for Machine Learning ]]>
                </title>
                <description>
                    <![CDATA[ By Davis David Tree-based algorithms are popular machine learning methods used to solve supervised learning problems. These algorithms are flexible and can solve any kind of problem at hand (classification or regression). Tree-based algorithms tend t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-the-tree-based-algorithm-for-machine-learning/</link>
                <guid isPermaLink="false">66d84ebdc8d279d4f28c47a1</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 06 Aug 2020 21:53:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/0_hOa0fVvazQigNgB2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Davis David</p>
<p>Tree-based algorithms are popular machine learning methods used to solve supervised learning problems. These algorithms are flexible and can solve any kind of problem at hand (classification or regression).</p>
<p>Tree-based algorithms tend to use the <strong>mean</strong> for continuous features or <strong>mode</strong> for categorical features when making predictions on training samples in the regions they belong to. They also produce predictions with <strong>high accuracy</strong>, <strong>stability</strong>, and <strong>ease</strong> <strong>of interpretation</strong>.</p>
<h1 id="heading-examples-of-tree-based-algorithms">Examples of Tree-based Algorithms</h1>
<p>There are different tree-based algorithms that you can use, such as</p>
<ul>
<li>Decision Trees</li>
<li>Random Forest</li>
<li>Gradient Boosting</li>
<li>Bagging (Bootstrap Aggregation)</li>
</ul>
<p>So every data scientist should learn these algorithms and use them in their machine learning projects.</p>
<p>In this article, you will learn more about the Random forest algorithm. After completing this article, you should be proficient at using the random forest algorithm to solve and build predictive models for classification problems with scikit-learn.</p>
<h1 id="heading-what-is-random-forest">What is Random Forest?</h1>
<p>Random forest is one of the most popular tree-based supervised learning algorithms. It is also the most flexible and easy to use. </p>
<p>The algorithm can be used to solve both classification and regression problems. Random forest tends to combine hundreds of <strong>decision trees</strong> and then trains each decision tree on a different sample of the observations. </p>
<p>The final predictions of the random forest are made by averaging the predictions of each individual tree.</p>
<p>The benefits of random forests are numerous. The individual decision trees tend to <strong>overfit</strong> to the training data but random forest can mitigate that issue by <strong>averaging</strong> the prediction results from different trees. This gives random forests a higher predictive accuracy than a single decision tree.</p>
<p>The random forest algorithm can also help you to find features that are <strong>important</strong> in your dataset. It lies at the base of the <a target="_blank" href="https://towardsdatascience.com/boruta-explained-the-way-i-wish-someone-explained-it-to-me-4489d70e154a">Boruta algorithm</a>, which selects important features in a dataset.</p>
<p>Random forest has been used in a variety of applications, for example to provide recommendations of different products to customers in e-commerce. </p>
<p>In medicine, a random forest algorithm can be used to identify the patient’s disease by analyzing the patient’s medical record. </p>
<p>Also in the banking sector, it can be used to easily determine whether the customer is fraudulent or legitimate.</p>
<h1 id="heading-how-does-the-random-forest-algorithm-work">How does the Random Forest algorithm work?</h1>
<p>The random forest algorithm works by completing the following steps:</p>
<p><strong>Step 1</strong>: The algorithm select random samples from the dataset provided.</p>
<p><strong>Step 2:</strong>  The algorithm will create a decision tree for each sample selected. Then it will get a prediction result from each decision tree created.</p>
<p><strong>Step 3: V</strong>oting will then be performed for every predicted result. For a classification problem, it will use <strong>mode</strong>, and for a regression problem, it will use <strong>mean</strong>.</p>
<p><strong>Step 4</strong>: And finally, the algorithm will select the most voted prediction result as the final prediction.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/how-random-forest-classifier-work.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>how it works</em></p>
<h1 id="heading-random-forest-in-practice">Random Forest in Practice</h1>
<p>Now that you know the ins and outs of the random forest algorithm, let's build a random forest classifier. </p>
<p>We will build a random forest classifier using the Pima Indians Diabetes dataset. The Pima Indians Diabetes Dataset involves predicting the onset of diabetes within 5 years based on provided medical details. This is a binary classification problem. </p>
<p>Our task is to analyze and create a model on the Pima Indian Diabetes dataset to predict if a particular patient is at a risk of developing diabetes, given other independent factors.</p>
<p>We will start by importing important packages that we will use to load the dataset and create a random forest classifier. We will use the <a target="_blank" href="http://scikit-learn.org/stable/tutorial/index.html">scikit-learn</a> library to load and use the random forest algorithm.</p>
<pre><code class="lang-python"><span class="hljs-comment"># import important packages</span>
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns

%matplotlib inline

<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
<span class="hljs-keyword">from</span> sklearn.ensemble <span class="hljs-keyword">import</span> RandomForestClassifier
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> accuracy_score
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> StandardScaler, MinMaxScaler
<span class="hljs-keyword">import</span> pandas_profiling

<span class="hljs-keyword">from</span> matplotlib <span class="hljs-keyword">import</span> rcParams
<span class="hljs-keyword">import</span> warnings

warnings.filterwarnings(<span class="hljs-string">"ignore"</span>)

<span class="hljs-comment"># figure size in inches</span>
rcParams[<span class="hljs-string">"figure.figsize"</span>] = <span class="hljs-number">10</span>, <span class="hljs-number">6</span>
np.random.seed(<span class="hljs-number">42</span>)
</code></pre>
<h3 id="heading-dataset">Dataset</h3>
<p>Then load the dataset from the data directory:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Load dataset</span>
data = pd.read_csv(<span class="hljs-string">"../data/pima_indians_diabetes.csv"</span>)
</code></pre>
<p>Now we can observe the sample of the dataset.</p>
<pre><code class="lang-python">
<span class="hljs-comment"># show sample of the dataset</span>
data.sample(<span class="hljs-number">5</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/5-rows.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, in our dataset we have different features with numerical values.</p>
<p>Let's understand the list of features we have in this dataset.</p>
<pre><code class="lang-python"><span class="hljs-comment"># show columns</span>
data.columns
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/columns.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this dataset, there are 8 input features and 1 output / target feature. Missing values are believed to be encoded with zero values. The meaning of the variable names are as follows (from the first to the last feature):</p>
<ul>
<li>Number of times pregnant.</li>
<li>Plasma glucose concentration a 2 hours in an oral glucose tolerance test.</li>
<li>Diastolic blood pressure (mm Hg).</li>
<li>Triceps skinfold thickness (mm).</li>
<li>2-hour serum insulin (mu U/ml).</li>
<li>Body mass index (weight in kg/(height in m)^2).</li>
<li>Diabetes pedigree function.</li>
<li>Age (years).</li>
<li>Class variable (0 or 1).</li>
</ul>
<p>Then we split the dataset into independent features and target feature. Our target feature for this dataset is called <strong>class.</strong> </p>
<pre><code class="lang-python"><span class="hljs-comment"># split data into input and taget variable(s)</span>

X = data.drop(<span class="hljs-string">"class"</span>, axis=<span class="hljs-number">1</span>)
y = data[<span class="hljs-string">"class"</span>]
</code></pre>
<h3 id="heading-preprocessing-the-dataset">Preprocessing the Dataset</h3>
<p>Before we create a model we need to standardize our independent features by using the <code>standardScaler</code> method from scikit-learn.</p>
<pre><code class="lang-python"><span class="hljs-comment"># standardize the dataset</span>
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
</code></pre>
<p>You can learn more on how and why to standardize your data from this article by clicking <a target="_blank" href="https://towardsdatascience.com/how-and-why-to-standardize-your-data-996926c2c832">here</a>.</p>
<h3 id="heading-splitting-the-dataset-into-training-and-test-data">Splitting the dataset into Training and Test data</h3>
<p>We now split our processed dataset into training and test data. The test data will be 10% of the entire processed dataset.</p>
<pre><code class="lang-python"><span class="hljs-comment"># split into train and test set</span>
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, stratify=y, test_size=<span class="hljs-number">0.10</span>, random_state=<span class="hljs-number">42</span>
)
</code></pre>
<h3 id="heading-building-the-random-forest-classifier">Building the Random Forest Classifier</h3>
<p>Now is time to create our random forest classifier and then train it on the train set. We will also pass the number of trees (100) in the forest we want to use through the parameter called <strong>n_estimators.</strong> </p>
<pre><code class="lang-python"><span class="hljs-comment"># create the classifier</span>
classifier = RandomForestClassifier(n_estimators=<span class="hljs-number">100</span>)

<span class="hljs-comment"># Train the model using the training sets</span>
classifier.fit(X_train, y_train)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/default-parameters.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The above output shows different parameter values of the random forest classifier used during the training process on the train data. </p>
<p>After training we can perform prediction on the test data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># predictin on the test set</span>
y_pred = classifier.predict(X_test)
</code></pre>
<p> Then we check the accuracy using actual and predicted values from the test data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate Model Accuracy</span>
print(<span class="hljs-string">"Accuracy:"</span>, accuracy_score(y_test, y_pred))
</code></pre>
<p>Accuracy: 0.8051948051948052</p>
<p>Our accuracy is around 80.5% which is good. But we can always make it better.</p>
<h3 id="heading-identify-important-features">Identify Important Features</h3>
<p>As I said before, we can also check the important features by using the <strong>feature<em>importances</em></strong> variable from the random forest algorithm in scikit-learn.</p>
<pre><code class="lang-python"><span class="hljs-comment"># check Important features</span>
feature_importances_df = pd.DataFrame(
    {<span class="hljs-string">"feature"</span>: list(X.columns), <span class="hljs-string">"importance"</span>: classifier.feature_importances_}
).sort_values(<span class="hljs-string">"importance"</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Display</span>
feature_importances_df
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/feature-importance-list.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Important Features</em></p>
<p>The figure above shows the relative importance of features and their contribution to the model. We can also visualize these features and their  scores using the seaborn and matplotlib libraries.</p>
<pre><code class="lang-python"><span class="hljs-comment"># visualize important featuers</span>

<span class="hljs-comment"># Creating a bar plot</span>
sns.barplot(x=feature_importances_df.feature, y=feature_importances_df.importance)
<span class="hljs-comment"># Add labels to your</span>

plt.xlabel(<span class="hljs-string">"Feature Importance Score"</span>)
plt.ylabel(<span class="hljs-string">"Features"</span>)
plt.title(<span class="hljs-string">"Visualizing Important Features"</span>)
plt.xticks(
    rotation=<span class="hljs-number">45</span>, horizontalalignment=<span class="hljs-string">"right"</span>, fontweight=<span class="hljs-string">"light"</span>, fontsize=<span class="hljs-string">"x-large"</span>
)
plt.show()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/visualize-feature-importance.PNG" alt="Image" width="600" height="400" loading="lazy"></p>
<p>From the figure above, you can see the <strong>triceps_skinfold_thickness feature</strong> has low importance and does not contribute much to the prediction. </p>
<p>This means that we can remove this feature and train our random forest classifier again and then see if it can improve its performance on the test data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># load data with selected features</span>
X = data.drop([<span class="hljs-string">"class"</span>, <span class="hljs-string">"triceps_skinfold_thickness"</span>], axis=<span class="hljs-number">1</span>)
y = data[<span class="hljs-string">"class"</span>]

<span class="hljs-comment"># standardize the dataset</span>
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

<span class="hljs-comment"># split into train and test set</span>
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, stratify=y, test_size=<span class="hljs-number">0.10</span>, random_state=<span class="hljs-number">42</span>
)
</code></pre>
<p>We will train the random forest algorithm with the selected processed features from our dataset, perform predictions, and then find the accuracy of the model.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Create a Random Classifier</span>
clf = RandomForestClassifier(n_estimators=<span class="hljs-number">100</span>)

<span class="hljs-comment"># Train the model using the training sets</span>
clf.fit(X_train, y_train)

<span class="hljs-comment"># prediction on test set</span>
y_pred = clf.predict(X_test)

<span class="hljs-comment"># Calculate Model Accuracy,</span>
print(<span class="hljs-string">"Accuracy:"</span>, accuracy_score(y_test, y_pred))
</code></pre>
<p>Accuracy: 0.8181818181818182</p>
<p>Now the model accuracy has increased from <strong>80.5%</strong> to <strong>81.8%</strong> after we removed the least important feature called _triceps_skinfold<em>thickness</em>. </p>
<p>This suggests that it is very important to check important features and see if you can remove the least important features to increase your model's performance.</p>
<h1 id="heading-wrapping-up">Wrapping up</h1>
<p>Tree-based algorithms are really important for every data scientist to learn. In this article, you've learned the basics of tree-based algorithms and how to create a classification model by using the random forest algorithm. </p>
<p>I also recommend you try other types of tree-based algorithms such as the <a target="_blank" href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html#sklearn.ensemble.ExtraTreesClassifier">Extra-trees algorithm</a>.</p>
<p>You can download the dataset and notebook used in this article here: <a target="_blank" href="https://github.com/Davisy/Random-Forest-classification-Tutorial">https://github.com/Davisy/Random-Forest-classification-Tutorial</a></p>
<p>Congratulations, you have made it to the end of this article!</p>
<p>If you learned something new or enjoyed reading this article, please share it so that others can see it. Until then, see you in the next post! I can also be reached on Twitter <a target="_blank" href="https://twitter.com/Davis_McDavid">@Davis_McDavid</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Supercharge Your Depth First Search with Goroutines ]]>
                </title>
                <description>
                    <![CDATA[ By Aayush Joglekar What is Depth First Search? Depth first search is a popular graph traversal algorithm. One application of depth first search in real world applications is in site mapping. A site map is a list of pages of a web site. They are organ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/supercharge-your-dfs-with-goroutines/</link>
                <guid isPermaLink="false">66d45d5d230dff0166905797</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 22 May 2020 01:49:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/Frame-1-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Aayush Joglekar</p>
<h2 id="heading-what-is-depth-first-search">What is Depth First Search?</h2>
<p>Depth first search is a popular graph traversal algorithm. One application of depth first search in real world applications is in site mapping.</p>
<p>A site map is a list of pages of a web site. They are organised in a hierarchical manner and describe the whole structure of a website starting from a root node.</p>
<h3 id="heading-the-algorithm">The Algorithm</h3>
<p>Site mapping involves loading a root link, parsing the internal links on the page and then recursively applying the same process to those links. This gives us a graph data structure, but for simplicity, we can assume that it's a tree.</p>
<h3 id="heading-the-problem">The Problem</h3>
<p>If we implemented the algorithm that way, loading and parsing HTML pages takes time and blocks the whole traversal process. </p>
<p>Suppose an HTTP response takes an average of <em>300ms</em> and there are 100 pages on the site to map. 300*100 = 30000ms =&gt; 30 seconds. So, the process will remain idle for 300 seconds.</p>
<h2 id="heading-how-can-we-improve-this">How Can We Improve This?</h2>
<p>In the time that a page loads, you can send multiple HTTP requests and parse the received HTML pages if you implement a multi-threaded architecture.</p>
<p>This concurrent method is <strong>7x faster</strong> than the one previously mentioned.</p>
<p>Implementing threads may set off the alarm bell in many developers' mind. However, Golang provides you with a beautiful set of concepts like goroutines, channels, and synchronization utilities to make the job much easier.</p>
<p>I talked about site mapping earlier, however, it is much better and simpler if you learn how to program a depth first search algorithm for a binary tree. You can apply what you'll learn in this article to a lot of different things.</p>
<p>Let's get started!</p>
<p>You can find the code used in this article here on <a target="_blank" href="https://github.com/zerefwayne/article-snippets/tree/master/supercharge-dfs-with-goroutines">GitHub</a>.</p>
<h2 id="heading-setting-up-the-tree">Setting Up the Tree</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Group-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-node-definition">Node Definition</h3>
<p>A node struct is the basic building block of your binary tree. It has a data, a left child and right child pointer. To simulate the delay in processing a node, you have to assign a random sleep time in microseconds.</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Node <span class="hljs-keyword">struct</span> {
    Data <span class="hljs-keyword">interface</span>{}
    Sleep time.Duration
    Left *Node
    Right *Node
}
</code></pre>
<h3 id="heading-node-generator-function">Node Generator Function</h3>
<p><code>NewNode()</code> returns a pointer to the a new node. Sleep is assigned a duration of 0-100 microseconds.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewNode</span><span class="hljs-params">(data <span class="hljs-keyword">interface</span>{})</span> *<span class="hljs-title">Node</span></span> {

    node := <span class="hljs-built_in">new</span>(Node)

    node.Data = data
    node.Left = <span class="hljs-literal">nil</span>
    node.Right = <span class="hljs-literal">nil</span>

    rand.Seed(time.Now().UTC().UnixNano())
    duration := <span class="hljs-keyword">int64</span>(rand.Intn(<span class="hljs-number">100</span>))
    node.Sleep = time.Duration(duration) * time.Microsecond

    <span class="hljs-keyword">return</span> node
}
</code></pre>
<p>Now you've set up your tree and can implement the depth first search and a function to process the node.</p>
<h2 id="heading-single-threaded-depth-first-search">Single-Threaded Depth First Search</h2>
<h3 id="heading-processnode">ProcessNode()</h3>
<p><code>ProcessNode()</code> is a function that will be invoked when the node has to be processed during a traversal. </p>
<p>Normally you would print or store the node's value. However, to show the benefits of goroutines, you'll have to implement a compute intensive task that takes somewhere around 1 second. </p>
<p>During each iteration, the node sleeps for <code>n.Sleep</code> microseconds and prints out <code>Node &lt;data&gt; ✅</code> once the task completes.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(n *Node)</span> <span class="hljs-title">ProcessNode</span><span class="hljs-params">()</span></span> {

    <span class="hljs-keyword">var</span> hello []<span class="hljs-keyword">int</span>

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10000</span>; i++ {
        time.Sleep(n.Sleep)
        hello = <span class="hljs-built_in">append</span>(hello, i)
    }

    fmt.Printf(<span class="hljs-string">"Node %v ✅\n"</span>, n.Data)
}
</code></pre>
<h3 id="heading-depth-first-search-recursive-function">Depth First Search Recursive Function</h3>
<p>This is a single-threaded depth first search function implemented via recursion — it might look familiar to those who have written it before.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(n *Node)</span> <span class="hljs-title">DFS</span><span class="hljs-params">()</span></span> {

    <span class="hljs-keyword">if</span> n == <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span>
    }

    n.Left.DFS()
    n.ProcessNode()
    n.Right.DFS()
}
</code></pre>
<h3 id="heading-implementing-the-main-function">Implementing the main() Function</h3>
<p>In the main function, create a complete binary tree that consists of 7 nodes.</p>
<p>To see how much time has elapsed, initiate <code>start</code> and then begin the DFS at the root. Once it completes, <code>main()</code> prints out the time that has elapsed.</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> wg sync.WaitGroup

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

    root := NewNode(<span class="hljs-number">1</span>)
    root.Left = NewNode(<span class="hljs-number">2</span>)
    root.Right = NewNode(<span class="hljs-number">3</span>)
    root.Left.Left = NewNode(<span class="hljs-number">4</span>)
    root.Left.Right = NewNode(<span class="hljs-number">5</span>)
    root.Right.Left = NewNode(<span class="hljs-number">6</span>)
    root.Right.Right = NewNode(<span class="hljs-number">7</span>)

    start := time.Now()
    root.DFS()
    fmt.Printf(<span class="hljs-string">"\nTime elapsed: %v\n\n"</span>, time.Since(start))

}
</code></pre>
<h3 id="heading-output">Output</h3>
<p>It took <code>8.75s</code> for the depth first search to complete.</p>
<p>Most of the time, the processor was idle as each node was being processed. It also prevented other nodes from processing while it completed its sleep time.</p>
<p>In the real world, this situation occurs during I/O or external HTTP calls.</p>
<pre><code>Node <span class="hljs-number">4</span> ✅
Node <span class="hljs-number">2</span> ✅
Node <span class="hljs-number">5</span> ✅
Node <span class="hljs-number">1</span> ✅
Node <span class="hljs-number">6</span> ✅
Node <span class="hljs-number">3</span> ✅
Node <span class="hljs-number">7</span> ✅

Time elapsed: <span class="hljs-number">8.75086767</span>s
</code></pre><h2 id="heading-supercharge-your-depth-first-search-with-goroutines">Supercharge Your Depth First Search with Goroutines</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://tenor.com/bd2iD.gif">https://tenor.com/bd2iD.gif</a></div>
<p>Converting the process and depth first search functions involves only minor changes when compared to other programming languages:</p>
<ol>
<li>Calling the recursive function with the <code>go</code> command.</li>
<li>Maintaining a <code>waitGroup</code> which keeps track of the in process function so the program doesn't exit without all of them completing.</li>
</ol>
<h3 id="heading-dfsparallel">DFSParallel()</h3>
<p><code>wg.Add(1)</code>: Before going into recursion, add the goroutine that will be started to the <code>waitGroup</code>.</p>
<p>You can also run <code>wg.Add(3)</code> and then start the three goroutines and it will do the job. However, this is more aesthetic and clearly denotes what is going to happen.</p>
<p><code>defer wg.Done()</code>: decreases the <code>waitGroup</code> counter by 1 when the function returns. This conveys that the routine has completed.</p>
<p><code>go</code>: Starts the function in a new goroutine.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(n *Node)</span> <span class="hljs-title">DFSParallel</span><span class="hljs-params">()</span></span> {

    <span class="hljs-keyword">defer</span> wg.Done()

    <span class="hljs-keyword">if</span> n == <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span>
    }

    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> n.Left.DFSParallel()

    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> n.ProcessNodeParallel()

    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">go</span> n.Right.DFSParallel()
}
</code></pre>
<h3 id="heading-processnodeparallel">ProcessNodeParallel()</h3>
<p>Nothing much to be done here, just add a <code>defer wg.Done()</code> after the function starts. It'll inform <code>waitGroup</code> that this goroutine has finished.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(n *Node)</span> <span class="hljs-title">ProcessNodeParallel</span><span class="hljs-params">()</span></span> {

    <span class="hljs-keyword">defer</span> wg.Done()

    <span class="hljs-keyword">var</span> hello []<span class="hljs-keyword">int</span>

    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10000</span>; i++ {
        time.Sleep(n.Sleep)
        hello = <span class="hljs-built_in">append</span>(hello, i)
    }

    fmt.Printf(<span class="hljs-string">"Node %v ✅\n"</span>, n.Data)
}
</code></pre>
<p>### </p>
<h3 id="heading-calling-dfsparallel-in-main">Calling DFSParallel() in main()</h3>
<p><code>GOMAXPROCS</code> tells the Go compiler to run threads on all logical cores available on the computer.</p>
<p>This will help you to process multiple nodes as well. The concurrent design pattern that has been implemented here shows the benefit of having multiple cores on the computer. Not only can the program process other nodes while one is sleeping, but it can also process multiple nodes at the same time.</p>
<p>You can start the <code>DFSParallel()</code> as a goroutine as before and add it to the wait group.</p>
<p><code>wg.Wait()</code> waits for all goroutines to be completed. It waits for the goroutines count to be 0 and then moves the control forward.</p>
<pre><code class="lang-go">...
    <span class="hljs-comment">// Go will use maximum number of processors available to process goroutines</span>
    processors := runtime.GOMAXPROCS(runtime.NumCPU())

    fmt.Printf(<span class="hljs-string">"\nTime elapsed: %v\n\n"</span>, time.Since(start))

    <span class="hljs-comment">// Starts the timer</span>
    start = time.Now()

    <span class="hljs-comment">// Adds one goroutine the WaitGroup</span>
    wg.Add(<span class="hljs-number">1</span>)
    <span class="hljs-comment">// Start the DFS Goroutine</span>
    <span class="hljs-keyword">go</span> root.DFSParallel()
    <span class="hljs-comment">// Waits for all goroutines to complete</span>
    wg.Wait()

    fmt.Printf(<span class="hljs-string">"\nProcessors: %v Time elapsed: %v\n"</span>, processors, time.Since(start))


}
</code></pre>
<h3 id="heading-output-1">Output</h3>
<pre><code>Node <span class="hljs-number">7</span> ✅
Node <span class="hljs-number">4</span> ✅
Node <span class="hljs-number">2</span> ✅
Node <span class="hljs-number">6</span> ✅
Node <span class="hljs-number">5</span> ✅
Node <span class="hljs-number">1</span> ✅
Node <span class="hljs-number">3</span> ✅

<span class="hljs-attr">Processors</span>: <span class="hljs-number">8</span> Time elapsed: <span class="hljs-number">1.295332809</span>s
</code></pre><p>As expected, the depth first search algorithm completes in just <strong>1.3 seconds</strong> as opposed to the <strong>8.7 seconds</strong> in the previous implementation.</p>
<h2 id="heading-explanation">Explanation</h2>
<h4 id="heading-normal-implementation">Normal Implementation</h4>
<p>The functions were running serially in a pre-ordered manner as you would expect. Each function was taking ~1.1 seconds to complete leading to the long run time. </p>
<p>However, each node sleeps for ~1 second as well, during which the processors remain idle as everything is running in one thread.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Group-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Normal Implementation Time Graph (x-axis in Seconds)</em></p>
<h4 id="heading-concurrent-implementation">Concurrent Implementation</h4>
<p>The functions were running independently and almost every one of them started at roughly ~ 0th second. They ran for 1 second and every thread completed. </p>
<p>However you can see that the order is not the same as the previous implementation. This is because they are running independently and finish at different times. Since they all started at roughly the same time, the traversal completed in roughly the duration of a single function's runtime.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Group-2--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Concurrent Implementation (x-axis in seconds)</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I found this result to be pretty amazing since it didn't take me more than a few concepts and 5-6 extra lines to make this program <strong>7x</strong> faster.</p>
<p>This technique can prove to be a major boost to your Go program if you can identify functions which can run independently at the same time. If your functions require synchronization, you can use channels to achieve that task.</p>
<p>You can find the code used in this article here on <a target="_blank" href="https://github.com/zerefwayne/article-snippets/tree/master/supercharge-dfs-with-goroutines">GitHub</a>.</p>
<h2 id="heading-supplementary-stuff">Supplementary Stuff</h2>
<ol>
<li><a target="_blank" href="https://medium.com/rungo/anatomy-of-goroutines-in-go-concurrency-in-go-a4cb9272ff88">https://medium.com/rungo/anatomy-of-goroutines-in-go-concurrency-in-go-a4cb9272ff88</a></li>
<li><a target="_blank" href="https://blog.golang.org/defer-panic-and-recover">https://blog.golang.org/defer-panic-and-recover</a></li>
<li><a target="_blank" href="https://medium.com/@houzier.saurav/dfs-and-bfs-golang-d5818ec690d3">https://medium.com/@houzier.saurav/dfs-and-bfs-golang-d5818ec690d3</a></li>
<li><a target="_blank" href="https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb">https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb</a></li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Learn Tree Data Structures the Codeless Way ]]>
                </title>
                <description>
                    <![CDATA[ By Armstrong Subero The tree data structure can form some of the most useful and complex data structures in all of programming. In fact the tree is so powerful that I can make the bold claim: Once you understand trees you'll be able to understand man... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-codeless-guide-to-tree-data-structures/</link>
                <guid isPermaLink="false">66d45d9ed62e921b49e02cc0</guid>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 09 Mar 2020 23:16:20 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9c36740569d1a4ca30b5.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Armstrong Subero</p>
<p>The tree data structure can form some of the most useful and complex data structures in all of programming. In fact the tree is so powerful that I can make the bold claim:</p>
<p><strong>Once you understand trees you'll be able to understand many other data structures and algorithms with ease.</strong></p>
<p>There is one caveat. There are so many types of trees it may be impossible to know where to start! There are B-trees, Red Black Trees, Binary Trees, AVL Trees and many others. There are abundant choices and each seems valuable to learn.</p>
<p>This presents a problem. As someone learning about trees you may find yourself asking, which tree data structure do I learn about first? Which tree is most important for me? There are so many, where do I start?</p>
<p>Learning about trees is like learning about the numerous marvels in our current world. We have a lot of choices, in fact we may even have too much choice. </p>
<p>Psychologists call it <strong>Overchoice</strong> or "<strong>choice overload</strong>", that is when faced with many options, people have a difficult choice deciding on what to do. I call it a beginning coder's worst nightmare. </p>
<p>However there is no need to panic. From my knowledge of using the tree data structure, as with most things in life, the Pareto principle (what we call the 80/20 rule) applies. </p>
<p>What this means is that as a programmer, 80% of cases where you will need to use trees will be covered by approximately 20% of the types of trees that you will attempt to learn.</p>
<p>For this reason we will focus only on these 20% which I think are the most important trees you need to understand. Don't get me wrong here, I'm not saying don't learn other types of trees. I'm saying learn these first, then focus on the others to really get that edge. </p>
<p>Even when you do figure out which tree data structure you want to learn, you are faced with another problem.</p>
<p>There are a lot of resources out there that teach you about trees, however they all present you with some code in a particular language be it JavaScript, Java, Python or others as part of the explanation. </p>
<p><strong>In this post I break that status quo and teach you about the essential tree data structures, and all without having you write a single line of code.</strong></p>
<p>Join me on a journey into the world of trees, regardless of which programming language you are using, you will be able to learn all the basics you need to know about the tree data structure.</p>
<h2 id="heading-getting-to-the-root-of-trees">Getting to the Root of Trees</h2>
<p>Let's get to the root of our discussion (pun intended). The way I like to explain trees is by relating it to something we are all familiar with, that of the biological tree. In case you are not familiar, let's look at one right now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/photography-of-tree-1067333.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>A Biological Tree</em></p>
<p>Look at our tree, isn't it beautiful!? We see that a tree is a giant plant with a trunk, a branch and leaves. There are also roots hidden beneath the ground that also form part of the organism. </p>
<p>A tree in computer science isn't so different. Let's look at one here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-23.png" alt="Image" width="600" height="400" loading="lazy">
<em>A Computer Science Tree</em></p>
<p>A computer science tree is very similar to a regular tree – it resembles an upside down biological tree a little doesn't it? It not only looks similar, but it also has parts that are named similar to our good ol' tangible tree. </p>
<p>Before we learn about the types of trees though, there are a few facts about trees you must know.</p>
<h3 id="heading-here-are-5-facts-you-need-to-know-about-trees">Here are 5 facts you need to know about trees:</h3>
<ol>
<li><p>Each of the circles in the tree is called a node and each line is called an edge.</p>
</li>
<li><p>The root node is the part of the tree that all the other parts are built upon. </p>
</li>
<li><p>There are parent nodes connected to other nodes in the direction of the root, and         child nodes connected in the direction away from the root.</p>
</li>
<li><p>The last nodes of the trees are called leaves</p>
</li>
<li><p>The process of navigating a tree is called traversal. </p>
</li>
</ol>
<p>If you like to see things visually, here is a diagram of the tree we looked at earlier identifying the parts:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our Labelled Tree</em></p>
<p>You should also know that when a tree is the child of a node, it is called a subtree. Look at the diagram above, the node labelled "Parent" along with its two child nodes can be classified as a subtree. </p>
<p>Great, now you have an idea about basic trees. So let's dive into some of the most useful type of trees you will encounter.</p>
<h2 id="heading-the-general-tree">The General Tree</h2>
<p>The first type of tree we need to know about is the general tree. The general tree is what we call a superset. This is because all other types of trees are derived from the general tree. </p>
<p>Trees are hierarchical in the way they store data. Whereas simpler data structures may store data in a linear manner (think an array), trees are non-linear. </p>
<p>The general tree is the embodiment of a hierarchical tree structure as it has no restrictions on how many children each node can have, and has no restraint imposed on the hierarchy of the tree.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of A General Tree</em></p>
<h2 id="heading-the-binary-tree">The Binary Tree</h2>
<p>It is impossible to talk about trees without talking about the binary tree (okay not totally impossible, but you know what I mean).</p>
<p>Simply put, a binary tree is a type of tree that has a restriction. In the binary tree, each parent can only be linked to two child nodes within the tree. </p>
<p>There is one binary tree type that illustrates this best: the binary search tree. Trees you see aren't just empty circles connected by lines. Each of the node in the tree has a value associated with it and the entirety of the tree is a key-value structure. </p>
<p>Binary search trees keep their keys sorted. They sort it like this: all the nodes are greater that the nodes in their left subtree, but are smaller than the nodes in their right subtree. Confused? Maybe a picture will help:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>A Binary Search Tree</em></p>
<p>Look closely at this tree and you will learn a little secret. In the binary tree the smallest node is located at the leftmost subtree stemming from the root node. Wanna guess where we can find the largest node?</p>
<h2 id="heading-red-black-tree">Red-Black Tree</h2>
<p>Let's look at a variant of the binary search tree that people tend to over-complicate. I'm talking about the Red-Black Tree. </p>
<p>There are many cases of trees where data may be inserted and deleted. So variations of the binary search tree have been created which makes this constant insertion and deletion more efficient.</p>
<p>The Red-Black tree is one such configuration of the binary search tree that makes the insertion and deletion process more efficient. </p>
<p>The tree does this by having a bit that adds an attribute to the node. This attribute that is added on the node is color, and this color can be interpreted as red or black. Hence the name Red-Black tree. </p>
<p>Let's look at how a Red-Black tree many be arranged:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>A Red-Black Tree</em></p>
<p>In the Red-Black tree, the root node is usually black and each red node has children that are black. </p>
<p>If you made it this far, then congratulations! You already understand enough to make a foray into the world of tree data structures. </p>
<h2 id="heading-where-are-trees-used">Where Are Trees Used?</h2>
<p>At this point you may be wondering what trees are used for. That's a good question! Trees are used in many facets of development including use in:</p>
<ol>
<li>Databases</li>
<li>Compilers</li>
<li>Networking</li>
<li>Heaps</li>
<li>Machine Learning Algorithms</li>
</ol>
<p>There are countless uses for trees and the only limit in their use is the imagination of the designer.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this post we began our journey into the world of the tree. Even though we covered some ground, we merely scrapped the surface of this vast and intricate data structure. </p>
<p>We whet our appetite for tree data structures by covering what trees are and looked at their structure. We then discussed three common types of trees including general trees, binary trees and red-black trees. Finally we looked at some places where trees may be used.</p>
<p>By the end of this post you should have a solid foundation to venture into the world of trees!</p>
<h2 id="heading-where-to-go-next">Where to Go Next?</h2>
<p>Want to learn about trees and other data structures without writing a single line of code? The pick up the book "Codeless Data Structures and Algorithms", where you'll learn all you need to know about data structures and algorithms without writing a single line of code!</p>
<p>We will not only greatly expand on what we learned, but we'll cover juicy topics not covered here like tree balancing, AVL trees, B-Trees, Heaps and a ton of topics in the realm of data structures and algorithms!</p>
<p>You can read the book here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.apress.com/gp/book/9781484257241">https://www.apress.com/gp/book/9781484257241</a></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ AVL Tree Insertion and Rotation ]]>
                </title>
                <description>
                    <![CDATA[ An AVL tree is an improved version of the binary search tree (BST) that is self-balancing. It was named after its inventors Adelson-Velsky and Landis, and was first introduced in 1962, just two years after the design of the binary search tree in 1960... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/avl-tree/</link>
                <guid isPermaLink="false">66c345295ced6d98e4bd3295</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ binary search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ toothbrush ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 15 Jan 2020 22:10:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9dda740569d1a4ca39fa.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>An AVL tree is an improved version of the binary search tree (BST) that is self-balancing. It was named after its inventors <strong>A</strong>delson-<strong>V</strong>elsky and <strong>L</strong>andis, and was first introduced in 1962, just two years after the design of the binary search tree in 1960. The AVL tree is considered to be the first data structure of its type.</p>
<p>A BST is a data structure composed of nodes. It has the following guarantees:</p>
<ol>
<li>Each tree has a root node (at the top).</li>
<li>The root node has zero or more child nodes.</li>
<li>Each child node has zero or more child nodes, and so on.</li>
<li>Each node has up to two children.</li>
<li>For each node, its left descendants are less than the current node, which is less than the right descendants.</li>
</ol>
<p>AVL trees have an additional guarantee:</p>
<ol>
<li>The difference between the depth of right and left subtrees cannot be more than one. </li>
</ol>
<p>In order to maintain this guarantee, implementations of AVL trees include an algorithm to rebalance the tree when adding an additional element would cause the difference in depth between the right and left trees to be greater than one.</p>
<p>AVL trees have a worst case lookup, insert and delete time of O(log n).</p>
<h3 id="heading-right-rotation"><strong>Right Rotation</strong></h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/avl_right_rotation.jpg" alt="Image" width="600" height="400" loading="lazy">
_Source: <a target="_blank" href="https://github.com/HebleV/valet_parking/tree/master/images">https://github.com/HebleV/valet_parking/tree/master/images</a>_</p>
<h3 id="heading-left-rotation"><strong>Left Rotation</strong></h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/avl_left_rotation.jpg" alt="Image" width="600" height="400" loading="lazy">
_Source: <a target="_blank" href="https://github.com/HebleV/valet_parking/tree/master/images">https://github.com/HebleV/valet_parking/tree/master/images</a>_</p>
<h3 id="heading-avl-insertion-process"><strong>AVL Insertion Process</strong></h3>
<p>This works similarly to a normal binary search tree insertion. After the insertion, you fix the AVL property by using left or right rotations.</p>
<ul>
<li>If there is an imbalance in left child of right subtree, then you perform a left-right rotation.</li>
<li>If there is an imbalance in left child of left subtree, then you perform a right rotation.</li>
<li>If there is an imbalance in right child of right subtree, then you perform a left rotation.</li>
<li>If there is an imbalance in right child of left subtree, then you perform a right-left rotation.</li>
</ul>
<h3 id="heading-example">Example</h3>
<p>Here's an example of an AVL tree in Python:</p>
<pre><code class="lang-py"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">node</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,value=None</span>):</span>
        self.value=value
        self.left_child=<span class="hljs-literal">None</span>
        self.right_child=<span class="hljs-literal">None</span>
        self.parent=<span class="hljs-literal">None</span> <span class="hljs-comment"># pointer to parent node in tree</span>
        self.height=<span class="hljs-number">1</span> <span class="hljs-comment"># height of node in tree (max dist. to leaf) NEW FOR AVL</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AVLTree</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.root=<span class="hljs-literal">None</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.root==<span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>
        content=<span class="hljs-string">'\n'</span> <span class="hljs-comment"># to hold final string</span>
        cur_nodes=[self.root] <span class="hljs-comment"># all nodes at current level</span>
        cur_height=self.root.height <span class="hljs-comment"># height of nodes at current level</span>
        sep=<span class="hljs-string">' '</span>*(<span class="hljs-number">2</span>**(cur_height<span class="hljs-number">-1</span>)) <span class="hljs-comment"># variable sized separator between elements</span>
        <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
            cur_height+=<span class="hljs-number">-1</span> <span class="hljs-comment"># decrement current height</span>
            <span class="hljs-keyword">if</span> len(cur_nodes)==<span class="hljs-number">0</span>: <span class="hljs-keyword">break</span>
            cur_row=<span class="hljs-string">' '</span>
            next_row=<span class="hljs-string">''</span>
            next_nodes=[]

            <span class="hljs-keyword">if</span> all(n <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> cur_nodes):
                <span class="hljs-keyword">break</span>

            <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> cur_nodes:

                <span class="hljs-keyword">if</span> n==<span class="hljs-literal">None</span>:
                    cur_row+=<span class="hljs-string">'   '</span>+sep
                    next_row+=<span class="hljs-string">'   '</span>+sep
                    next_nodes.extend([<span class="hljs-literal">None</span>,<span class="hljs-literal">None</span>])
                    <span class="hljs-keyword">continue</span>

                <span class="hljs-keyword">if</span> n.value!=<span class="hljs-literal">None</span>:       
                    buf=<span class="hljs-string">' '</span>*int((<span class="hljs-number">5</span>-len(str(n.value)))/<span class="hljs-number">2</span>)
                    cur_row+=<span class="hljs-string">'%s%s%s'</span>%(buf,str(n.value),buf)+sep
                <span class="hljs-keyword">else</span>:
                    cur_row+=<span class="hljs-string">' '</span>*<span class="hljs-number">5</span>+sep

                <span class="hljs-keyword">if</span> n.left_child!=<span class="hljs-literal">None</span>:  
                    next_nodes.append(n.left_child)
                    next_row+=<span class="hljs-string">' /'</span>+sep
                <span class="hljs-keyword">else</span>:
                    next_row+=<span class="hljs-string">'  '</span>+sep
                    next_nodes.append(<span class="hljs-literal">None</span>)

                <span class="hljs-keyword">if</span> n.right_child!=<span class="hljs-literal">None</span>: 
                    next_nodes.append(n.right_child)
                    next_row+=<span class="hljs-string">'\ '</span>+sep
                <span class="hljs-keyword">else</span>:
                    next_row+=<span class="hljs-string">'  '</span>+sep
                    next_nodes.append(<span class="hljs-literal">None</span>)

            content+=(cur_height*<span class="hljs-string">'   '</span>+cur_row+<span class="hljs-string">'\n'</span>+cur_height*<span class="hljs-string">'   '</span>+next_row+<span class="hljs-string">'\n'</span>)
            cur_nodes=next_nodes
            sep=<span class="hljs-string">' '</span>*int(len(sep)/<span class="hljs-number">2</span>) <span class="hljs-comment"># cut separator size in half</span>
        <span class="hljs-keyword">return</span> content

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">insert</span>(<span class="hljs-params">self,value</span>):</span>
        <span class="hljs-keyword">if</span> self.root==<span class="hljs-literal">None</span>:
            self.root=node(value)
        <span class="hljs-keyword">else</span>:
            self._insert(value,self.root)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_insert</span>(<span class="hljs-params">self,value,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> value&lt;cur_node.value:
            <span class="hljs-keyword">if</span> cur_node.left_child==<span class="hljs-literal">None</span>:
                cur_node.left_child=node(value)
                cur_node.left_child.parent=cur_node <span class="hljs-comment"># set parent</span>
                self._inspect_insertion(cur_node.left_child)
            <span class="hljs-keyword">else</span>:
                self._insert(value,cur_node.left_child)
        <span class="hljs-keyword">elif</span> value&gt;cur_node.value:
            <span class="hljs-keyword">if</span> cur_node.right_child==<span class="hljs-literal">None</span>:
                cur_node.right_child=node(value)
                cur_node.right_child.parent=cur_node <span class="hljs-comment"># set parent</span>
                self._inspect_insertion(cur_node.right_child)
            <span class="hljs-keyword">else</span>:
                self._insert(value,cur_node.right_child)
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">"Value already in tree!"</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_tree</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.root!=<span class="hljs-literal">None</span>:
            self._print_tree(self.root)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_print_tree</span>(<span class="hljs-params">self,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> cur_node!=<span class="hljs-literal">None</span>:
            self._print_tree(cur_node.left_child)
            <span class="hljs-keyword">print</span> (<span class="hljs-string">'%s, h=%d'</span>%(str(cur_node.value),cur_node.height))
            self._print_tree(cur_node.right_child)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">height</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.root!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._height(self.root,<span class="hljs-number">0</span>)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_height</span>(<span class="hljs-params">self,cur_node,cur_height</span>):</span>
        <span class="hljs-keyword">if</span> cur_node==<span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span> cur_height
        left_height=self._height(cur_node.left_child,cur_height+<span class="hljs-number">1</span>)
        right_height=self._height(cur_node.right_child,cur_height+<span class="hljs-number">1</span>)
        <span class="hljs-keyword">return</span> max(left_height,right_height)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">find</span>(<span class="hljs-params">self,value</span>):</span>
        <span class="hljs-keyword">if</span> self.root!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._find(value,self.root)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_find</span>(<span class="hljs-params">self,value,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> value==cur_node.value:
            <span class="hljs-keyword">return</span> cur_node
        <span class="hljs-keyword">elif</span> value&lt;cur_node.value <span class="hljs-keyword">and</span> cur_node.left_child!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._find(value,cur_node.left_child)
        <span class="hljs-keyword">elif</span> value&gt;cur_node.value <span class="hljs-keyword">and</span> cur_node.right_child!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._find(value,cur_node.right_child)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_value</span>(<span class="hljs-params">self,value</span>):</span>
        <span class="hljs-keyword">return</span> self.delete_node(self.find(value))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_node</span>(<span class="hljs-params">self,node</span>):</span>

        <span class="hljs-comment">## -----</span>
        <span class="hljs-comment"># Improvements since prior lesson</span>

        <span class="hljs-comment"># Protect against deleting a node not found in the tree</span>
        <span class="hljs-keyword">if</span> node==<span class="hljs-literal">None</span> <span class="hljs-keyword">or</span> self.find(node.value)==<span class="hljs-literal">None</span>:
            print(<span class="hljs-string">"Node to be deleted not found in the tree!"</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span> 
        <span class="hljs-comment">## -----</span>

        <span class="hljs-comment"># returns the node with min value in tree rooted at input node</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">min_value_node</span>(<span class="hljs-params">n</span>):</span>
            current=n
            <span class="hljs-keyword">while</span> current.left_child!=<span class="hljs-literal">None</span>:
                current=current.left_child
            <span class="hljs-keyword">return</span> current

        <span class="hljs-comment"># returns the number of children for the specified node</span>
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">num_children</span>(<span class="hljs-params">n</span>):</span>
            num_children=<span class="hljs-number">0</span>
            <span class="hljs-keyword">if</span> n.left_child!=<span class="hljs-literal">None</span>: num_children+=<span class="hljs-number">1</span>
            <span class="hljs-keyword">if</span> n.right_child!=<span class="hljs-literal">None</span>: num_children+=<span class="hljs-number">1</span>
            <span class="hljs-keyword">return</span> num_children

        <span class="hljs-comment"># get the parent of the node to be deleted</span>
        node_parent=node.parent

        <span class="hljs-comment"># get the number of children of the node to be deleted</span>
        node_children=num_children(node)

        <span class="hljs-comment"># break operation into different cases based on the</span>
        <span class="hljs-comment"># structure of the tree &amp; node to be deleted</span>

        <span class="hljs-comment"># CASE 1 (node has no children)</span>
        <span class="hljs-keyword">if</span> node_children==<span class="hljs-number">0</span>:

            <span class="hljs-keyword">if</span> node_parent!=<span class="hljs-literal">None</span>:
                <span class="hljs-comment"># remove reference to the node from the parent</span>
                <span class="hljs-keyword">if</span> node_parent.left_child==node:
                    node_parent.left_child=<span class="hljs-literal">None</span>
                <span class="hljs-keyword">else</span>:
                    node_parent.right_child=<span class="hljs-literal">None</span>
            <span class="hljs-keyword">else</span>:
                self.root=<span class="hljs-literal">None</span>

        <span class="hljs-comment"># CASE 2 (node has a single child)</span>
        <span class="hljs-keyword">if</span> node_children==<span class="hljs-number">1</span>:

            <span class="hljs-comment"># get the single child node</span>
            <span class="hljs-keyword">if</span> node.left_child!=<span class="hljs-literal">None</span>:
                child=node.left_child
            <span class="hljs-keyword">else</span>:
                child=node.right_child

            <span class="hljs-keyword">if</span> node_parent!=<span class="hljs-literal">None</span>:
                <span class="hljs-comment"># replace the node to be deleted with its child</span>
                <span class="hljs-keyword">if</span> node_parent.left_child==node:
                    node_parent.left_child=child
                <span class="hljs-keyword">else</span>:
                    node_parent.right_child=child
            <span class="hljs-keyword">else</span>:
                self.root=child

            <span class="hljs-comment"># correct the parent pointer in node</span>
            child.parent=node_parent

        <span class="hljs-comment"># CASE 3 (node has two children)</span>
        <span class="hljs-keyword">if</span> node_children==<span class="hljs-number">2</span>:

            <span class="hljs-comment"># get the inorder successor of the deleted node</span>
            successor=min_value_node(node.right_child)

            <span class="hljs-comment"># copy the inorder successor's value to the node formerly</span>
            <span class="hljs-comment"># holding the value we wished to delete</span>
            node.value=successor.value

            <span class="hljs-comment"># delete the inorder successor now that it's value was</span>
            <span class="hljs-comment"># copied into the other node</span>
            self.delete_node(successor)

            <span class="hljs-comment"># exit function so we don't call the _inspect_deletion twice</span>
            <span class="hljs-keyword">return</span>

        <span class="hljs-keyword">if</span> node_parent!=<span class="hljs-literal">None</span>:
            <span class="hljs-comment"># fix the height of the parent of current node</span>
            node_parent.height=<span class="hljs-number">1</span>+max(self.get_height(node_parent.left_child),self.get_height(node_parent.right_child))

            <span class="hljs-comment"># begin to traverse back up the tree checking if there are</span>
            <span class="hljs-comment"># any sections which now invalidate the AVL balance rules</span>
            self._inspect_deletion(node_parent)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self,value</span>):</span>
        <span class="hljs-keyword">if</span> self.root!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._search(value,self.root)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_search</span>(<span class="hljs-params">self,value,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> value==cur_node.value:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
        <span class="hljs-keyword">elif</span> value&lt;cur_node.value <span class="hljs-keyword">and</span> cur_node.left_child!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._search(value,cur_node.left_child)
        <span class="hljs-keyword">elif</span> value&gt;cur_node.value <span class="hljs-keyword">and</span> cur_node.right_child!=<span class="hljs-literal">None</span>:
            <span class="hljs-keyword">return</span> self._search(value,cur_node.right_child)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span> 


    <span class="hljs-comment"># Functions added for AVL...</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_inspect_insertion</span>(<span class="hljs-params">self,cur_node,path=[]</span>):</span>
        <span class="hljs-keyword">if</span> cur_node.parent==<span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span>
        path=[cur_node]+path

        left_height =self.get_height(cur_node.parent.left_child)
        right_height=self.get_height(cur_node.parent.right_child)

        <span class="hljs-keyword">if</span> abs(left_height-right_height)&gt;<span class="hljs-number">1</span>:
            path=[cur_node.parent]+path
            self._rebalance_node(path[<span class="hljs-number">0</span>],path[<span class="hljs-number">1</span>],path[<span class="hljs-number">2</span>])
            <span class="hljs-keyword">return</span>

        new_height=<span class="hljs-number">1</span>+cur_node.height 
        <span class="hljs-keyword">if</span> new_height&gt;cur_node.parent.height:
            cur_node.parent.height=new_height

        self._inspect_insertion(cur_node.parent,path)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_inspect_deletion</span>(<span class="hljs-params">self,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> cur_node==<span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span>

        left_height =self.get_height(cur_node.left_child)
        right_height=self.get_height(cur_node.right_child)

        <span class="hljs-keyword">if</span> abs(left_height-right_height)&gt;<span class="hljs-number">1</span>:
            y=self.taller_child(cur_node)
            x=self.taller_child(y)
            self._rebalance_node(cur_node,y,x)

        self._inspect_deletion(cur_node.parent)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_rebalance_node</span>(<span class="hljs-params">self,z,y,x</span>):</span>
        <span class="hljs-keyword">if</span> y==z.left_child <span class="hljs-keyword">and</span> x==y.left_child:
            self._right_rotate(z)
        <span class="hljs-keyword">elif</span> y==z.left_child <span class="hljs-keyword">and</span> x==y.right_child:
            self._left_rotate(y)
            self._right_rotate(z)
        <span class="hljs-keyword">elif</span> y==z.right_child <span class="hljs-keyword">and</span> x==y.right_child:
            self._left_rotate(z)
        <span class="hljs-keyword">elif</span> y==z.right_child <span class="hljs-keyword">and</span> x==y.left_child:
            self._right_rotate(y)
            self._left_rotate(z)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">'_rebalance_node: z,y,x node configuration not recognized!'</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_right_rotate</span>(<span class="hljs-params">self,z</span>):</span>
        sub_root=z.parent 
        y=z.left_child
        t3=y.right_child
        y.right_child=z
        z.parent=y
        z.left_child=t3
        <span class="hljs-keyword">if</span> t3!=<span class="hljs-literal">None</span>: t3.parent=z
        y.parent=sub_root
        <span class="hljs-keyword">if</span> y.parent==<span class="hljs-literal">None</span>:
                self.root=y
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">if</span> y.parent.left_child==z:
                y.parent.left_child=y
            <span class="hljs-keyword">else</span>:
                y.parent.right_child=y        
        z.height=<span class="hljs-number">1</span>+max(self.get_height(z.left_child),
            self.get_height(z.right_child))
        y.height=<span class="hljs-number">1</span>+max(self.get_height(y.left_child),
            self.get_height(y.right_child))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_left_rotate</span>(<span class="hljs-params">self,z</span>):</span>
        sub_root=z.parent 
        y=z.right_child
        t2=y.left_child
        y.left_child=z
        z.parent=y
        z.right_child=t2
        <span class="hljs-keyword">if</span> t2!=<span class="hljs-literal">None</span>: t2.parent=z
        y.parent=sub_root
        <span class="hljs-keyword">if</span> y.parent==<span class="hljs-literal">None</span>: 
            self.root=y
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">if</span> y.parent.left_child==z:
                y.parent.left_child=y
            <span class="hljs-keyword">else</span>:
                y.parent.right_child=y
        z.height=<span class="hljs-number">1</span>+max(self.get_height(z.left_child),
            self.get_height(z.right_child))
        y.height=<span class="hljs-number">1</span>+max(self.get_height(y.left_child),
            self.get_height(y.right_child))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_height</span>(<span class="hljs-params">self,cur_node</span>):</span>
        <span class="hljs-keyword">if</span> cur_node==<span class="hljs-literal">None</span>: <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
        <span class="hljs-keyword">return</span> cur_node.height

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">taller_child</span>(<span class="hljs-params">self,cur_node</span>):</span>
        left=self.get_height(cur_node.left_child)
        right=self.get_height(cur_node.right_child)
        <span class="hljs-keyword">return</span> cur_node.left_child <span class="hljs-keyword">if</span> left&gt;=right <span class="hljs-keyword">else</span> cur_node.right_child
</code></pre>
<h3 id="heading-more-info-on-binary-search">More info on binary search:</h3>
<ul>
<li><a target="_blank" href="https://guide.freecodecamp.org/algorithms/search-algorithms/binary-search/">Binary search basics</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/binary-search-tree-what-is-it/">Binary search trees explained with examples</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/binary-data-structures-an-intro-to-trees-and-heaps-in-javascript-962ab536cb42/">Binary data structures: intro to trees (and heaps)</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ B-Tree Self-Balancing Search Index Data Structures Explained ]]>
                </title>
                <description>
                    <![CDATA[ What is a B-Tree? B-Tree is a self-balancing search tree.  In most of the other self-balancing search trees (like AVL and Red Black Trees), it is assumed that everything is in main memory.  To understand use of B-Trees, we must think of huge amount o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/b-tree-self-balancing-search-index-data-structures-explained/</link>
                <guid isPermaLink="false">66c345389972b7c5c7624e10</guid>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 24 Nov 2019 18:26:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9f13740569d1a4ca40b1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-is-a-b-tree">What is a B-Tree?</h2>
<p>B-Tree is a self-balancing search tree. </p>
<p>In most of the other self-balancing search trees (like AVL and Red Black Trees), it is assumed that everything is in main memory. </p>
<p>To understand use of B-Trees, we must think of huge amount of data that cannot fit in main memory. When the number of keys is high, the data is read from disk in the form of blocks. Disk access time is very high compared to main memory access time. </p>
<p>The main idea of using B-Trees is to reduce the number of disk accesses. Most of the tree operations (search, insert, delete, max, min, etc) require O(h) disk accesses where h is height of the tree. B-tree is a fat tree. </p>
<p>Height of B-Trees is kept low by putting maximum possible keys in a B-Tree node. Generally, a B-Tree node size is kept equal to the disk block size. Since h is low for B-Tree, total disk accesses for most of the operations are reduced significantly compared to balanced Binary Search Trees like AVL Tree, Red Black Tree, etc.</p>
<p>Properties of B-Tree:</p>
<ol>
<li>All leaf nodes are at same level.</li>
<li>A B-Tree is defined by the term minimum degree ‘t’. The value of t depends upon disk block size.</li>
<li>Every node except root must contain at least t-1 keys. Root may contain minimum 1 key.</li>
<li>All nodes (including root) may contain at most 2t – 1 keys.</li>
<li>Number of children of a node is equal to the number of keys in it plus 1.</li>
<li>All keys of a node are sorted in increasing order. The child between two keys k1 and k2 contains all keys in range from k1 and k2.</li>
<li>B-Tree grows and shrinks from root which is unlike Binary Search Tree. Binary Search Trees grow downward and also shrink from downward.</li>
<li>Like other balanced Binary Search Trees, time complexity to search, insert and delete is O(Log(n)).</li>
</ol>
<h3 id="heading-search">Search:</h3>
<p>Search is similar to search in Binary Search Tree. Let the key to be searched be k. We start from root and recursively traverse down. For every visited non-leaf node, if the node has key, we simply return the node. Otherwise we recur down to the appropriate child (The child which is just before the first greater key) of the node. If we reach a leaf node and don’t find k in the leaf node, we return NULL.</p>
<h3 id="heading-traverse">Traverse:</h3>
<p>Traversal is also similar to Inorder traversal of Binary Tree. We start from the leftmost child, recursively print the leftmost child, then repeat the same process for remaining children and keys. In the end, recursively print the rightmost child.</p>
<h3 id="heading-insert">Insert</h3>
<p>First we search and find out to which node the key should belong to and we insert it into it. Afterwards we look for and fix these problems: If the number of keys is too high(greater than t - 1) then we move the middle key to the nodes parent. We do this recursively up until root. If the number of keys in the root is too high, then we make the middle key to be the new root of the whole tree and connect it to the node it was in before.</p>
<h3 id="heading-time-analysis-for-b-tree">Time Analysis for B-Tree:</h3>
<p>Suppose a B-tree has n elements and M is the maximum number of children a node can have. What is the maximum depth the tree could have? What is the minimum depth the tree could have?</p>
<ul>
<li>The worst-case depth (maximum depth) of a B-tree is: logM/2 n.</li>
<li>The best-case depth (minimum depth) of a B-tree is: logM n.</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Binary Search Trees: BST Explained with Examples ]]>
                </title>
                <description>
                    <![CDATA[ What is a Binary Search Tree? A tree is a data structure composed of nodes that has the following characteristics: Each tree has a root node at the top (also known as Parent Node) containing some value (can be any datatype). The root node has zero o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/binary-search-trees-bst-explained-with-examples/</link>
                <guid isPermaLink="false">66c3460f622ca5970af832fc</guid>
                
                    <category>
                        <![CDATA[ binary search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 16 Nov 2019 17:58:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9f48740569d1a4ca41c4.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-is-a-binary-search-tree">What is a Binary Search Tree?</h2>
<p>A tree is a data structure composed of nodes that has the following characteristics:</p>
<ol>
<li>Each tree has a root node at the top (also known as Parent Node) containing some value (can be any datatype).</li>
<li>The root node has zero or more child nodes.</li>
<li>Each child node has zero or more child nodes, and so on. This creates a subtree in the tree. Every node has its own subtree made up of its children and their children, etc. This means that every node on its own can be a tree.</li>
</ol>
<p>A binary search tree (BST) adds these two characteristics:</p>
<ol>
<li>Each node has a maximum of up to two children.</li>
<li>For each node, the values of its left descendent nodes are less than that of the current node, which in turn is less than the right descendent nodes (if any).</li>
</ol>
<p>The BST is built on the idea of the <a target="_blank" href="https://guide.freecodecamp.org/algorithms/search-algorithms/binary-search">binary search</a> algorithm, which allows for fast lookup, insertion and removal of nodes. The way that they are set up means that, on average, each comparison allows the operations to skip about half of the tree, so that each lookup, insertion or deletion takes time proportional to the logarithm of the number of items stored in the tree,  <code>O(log n)</code> . However, some times the worst case can happen, when the tree isn't balanced and the time complexity is  <code>O(n)</code>  for all three of these functions. That is why self-balancing trees (AVL, red-black, etc.) are a lot more effective than the basic BST.</p>
<p><strong>Worst case scenario example:</strong>  This can happen when you keep adding nodes that are  <em>always</em>  larger than the node before (its parent), the same can happen when you always add nodes with values lower than their parents.</p>
<h3 id="heading-basic-operations-on-a-bst">Basic operations on a BST</h3>
<ul>
<li>Create: creates an empty tree.</li>
<li>Insert: insert a node in the tree.</li>
<li>Search: Searches for a node in the tree.</li>
<li>Delete: deletes a node from the tree.</li>
<li>Inorder: in-order traversal of the tree.</li>
<li>Preorder: pre-order traversal of the tree.</li>
<li>Postorder: post-order traversal of the tree.</li>
</ul>
<h4 id="heading-create">Create</h4>
<p>Initially an empty tree without any nodes is created. The variable/identifier which must point to the root node is initialized with a  <code>NULL</code>  value.</p>
<h4 id="heading-search">Search</h4>
<p>You always start searching the tree at the root node and go down from there. You compare the data in each node with the one you are looking for. If the compared node doesn't match then you either proceed to the right child or the left child, which depends on the outcome of the following comparison: If the node that you are searching for is lower than the one you were comparing it with, you proceed to the left child, otherwise (if it's larger) you go to the right child. Why? Because the BST is structured (as per its definition), that the right child is always larger than the parent and the left child is always lesser.</p>
<h6 id="heading-breadth-first-search-bfs">Breadth-first search (BFS)</h6>
<p>Breadth first search is an algorithm used to traverse a BST. It begins at the root node and travels in a lateral manner (side to side), searching for the desired node. This type of search can be described as O(n) given that each node is visited once and the size of the tree directly correlates to the length of the search.</p>
<h6 id="heading-depth-first-search-dfs">Depth-first search (DFS)</h6>
<p>With a Depth-first search approach, we start with the root node and travel down a single branch. If the desired node is found along that branch, great, but if not, continue upwards and search unvisited nodes. This type of search also has a big O notation of O(n).</p>
<h4 id="heading-insert">Insert</h4>
<p>It is very similar to the search function. You again start at the root of the tree and go down recursively, searching for the right place to insert our new node, in the same way as explained in the search function. If a node with the same value is already in the tree, you can choose to either insert the duplicate or not. Some trees allow duplicates, some don't. It depends on the certain implementation.</p>
<h4 id="heading-deletion">Deletion</h4>
<p>There are 3 cases that can happen when you are trying to delete a node. If it has,</p>
<ol>
<li>No subtree (no children): This one is the easiest one. You can simply just delete the node, without any additional actions required.</li>
<li>One subtree (one child): You have to make sure that after the node is deleted, its child is then connected to the deleted node's parent.</li>
<li>Two subtrees (two children): You have to find and replace the node you want to delete with its inorder successor (the leftmost node in the right subtree).</li>
</ol>
<p>The time complexity for creating a tree is  <code>O(1)</code> . The time complexity for searching, inserting or deleting a node depends on the height of the tree  <code>h</code> , so the worst case is  <code>O(h)</code>  in case of skewed trees.</p>
<h4 id="heading-predecessor-of-a-node">Predecessor of a node</h4>
<p>Predecessors can be described as the node that would come right before the node you are currently at. To find the predecessor of the current node, look at the right-most/largest leaf node in the left subtree.</p>
<h4 id="heading-successor-of-a-node">Successor of a node</h4>
<p>Successors can be described as the node that would come right after the the current node. To find the successor of the current node, look at the left-most/smallest leaf node in the right subtree.</p>
<h3 id="heading-special-types-of-bt">Special types of BT</h3>
<ul>
<li>Heap</li>
<li>Red-black tree</li>
<li>B-tree</li>
<li>Splay tree</li>
<li>N-ary tree</li>
<li>Trie (Radix tree)</li>
</ul>
<h3 id="heading-runtime">Runtime</h3>
<p><strong>Data structure: BST</strong></p>
<ul>
<li>Worst-case performance:  <code>O(n)</code></li>
<li>Best-case performance:  <code>O(1)</code></li>
<li>Average performance:  <code>O(log n)</code></li>
<li>Worst-case space complexity:  <code>O(1)</code></li>
</ul>
<p>Where  <code>n</code>  is the number of nodes in the BST. Worst case is O(n) since BST can be unbalanced.</p>
<h3 id="heading-implementation-of-bst">Implementation of BST</h3>
<p>Here's a definition for a BST node having some data, referencing to its left and right child nodes.</p>
<pre><code>struct node {
   int data;
   struct node *leftChild;
   struct node *rightChild;
};
</code></pre><h4 id="heading-search-operation">Search Operation</h4>
<p>Whenever an element is to be searched, start searching from the root node. Then if the data is less than the key value, search for the element in the left subtree. Otherwise, search for the element in the right subtree. Follow the same algorithm for each node.</p>
<pre><code>struct node* search(int data){
   struct node *current = root;
   printf(<span class="hljs-string">"Visiting elements: "</span>);

   <span class="hljs-keyword">while</span>(current-&gt;data != data){

      <span class="hljs-keyword">if</span>(current != NULL) {
         printf(<span class="hljs-string">"%d "</span>,current-&gt;data);

         <span class="hljs-comment">//go to left tree</span>
         <span class="hljs-keyword">if</span>(current-&gt;data &gt; data){
            current = current-&gt;leftChild;
         }<span class="hljs-comment">//else go to right tree</span>
         <span class="hljs-keyword">else</span> {                
            current = current-&gt;rightChild;
         }

         <span class="hljs-comment">//not found</span>
         <span class="hljs-keyword">if</span>(current == NULL){
            <span class="hljs-keyword">return</span> NULL;
         }
      }            
   }
   <span class="hljs-keyword">return</span> current;
}
</code></pre><h4 id="heading-insert-operation">Insert Operation</h4>
<p>Whenever an element is to be inserted, first locate its proper location. Start searching from the root node, then if the data is less than the key value, search for the empty location in the left subtree and insert the data. Otherwise, search for the empty location in the right subtree and insert the data.</p>
<pre><code><span class="hljs-keyword">void</span> insert(int data) {
   struct node *tempNode = (struct node*) malloc(sizeof(struct node));
   struct node *current;
   struct node *parent;

   tempNode-&gt;data = data;
   tempNode-&gt;leftChild = NULL;
   tempNode-&gt;rightChild = NULL;

   <span class="hljs-comment">//if tree is empty</span>
   <span class="hljs-keyword">if</span>(root == NULL) {
      root = tempNode;
   } <span class="hljs-keyword">else</span> {
      current = root;
      parent = NULL;

      <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>) {                
         parent = current;

         <span class="hljs-comment">//go to left of the tree</span>
         <span class="hljs-keyword">if</span>(data &lt; parent-&gt;data) {
            current = current-&gt;leftChild;                
            <span class="hljs-comment">//insert to the left</span>

            <span class="hljs-keyword">if</span>(current == NULL) {
               parent-&gt;leftChild = tempNode;
               <span class="hljs-keyword">return</span>;
            }
         }<span class="hljs-comment">//go to right of the tree</span>
         <span class="hljs-keyword">else</span> {
            current = current-&gt;rightChild;

            <span class="hljs-comment">//insert to the right</span>
            <span class="hljs-keyword">if</span>(current == NULL) {
               parent-&gt;rightChild = tempNode;
               <span class="hljs-keyword">return</span>;
            }
         }
      }            
   }
}
</code></pre><h4 id="heading-delete-operation">Delete Operation</h4>
<pre><code><span class="hljs-keyword">void</span> deleteNode(struct node* root, int data){

    <span class="hljs-keyword">if</span> (root == NULL) root=tempnode; 

    <span class="hljs-keyword">if</span> (data &lt; root-&gt;key) 
        root-&gt;left = deleteNode(root-&gt;left, key); 


    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (key &gt; root-&gt;key) 
        root-&gt;right = deleteNode(root-&gt;right, key); 

    <span class="hljs-keyword">else</span>
    { 
        <span class="hljs-keyword">if</span> (root-&gt;left == NULL) 
        { 
            struct node *temp = root-&gt;right; 
            free(root); 
            <span class="hljs-keyword">return</span> temp; 
        } 
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (root-&gt;right == NULL) 
        { 
            struct node *temp = root-&gt;left; 
            free(root); 
            <span class="hljs-keyword">return</span> temp; 
        } 

        struct node* temp = minValueNode(root-&gt;right); 

        root-&gt;key = temp-&gt;key; 

        root-&gt;right = deleteNode(root-&gt;right, temp-&gt;key); 
    } 
    <span class="hljs-keyword">return</span> root; 

}
</code></pre><p>Binary search trees (BSTs) also give us quick access to predecessors and successors. Predecessors can be described as the node that would come right before the node you are currently at.</p>
<ul>
<li>To find the predecessor of the current node, look at the rightmost/largest leaf node in the left subtree. Successors can be described as the node that would come right after the node you are currently at.</li>
<li>To find the successor of the current node, look at the leftmost/smallest leaf node in the right subtree.</li>
</ul>
<h3 id="heading-lets-look-at-a-couple-of-procedures-operating-on-trees">Let's look at a couple of procedures operating on trees.</h3>
<p>Since trees are recursively defined, it's very common to write routines that operate on trees that are themselves recursive.</p>
<p>So for instance, if we want to calculate the height of a tree, that is the height of a root node, We can go ahead and recursively do that, going through the tree. So we can say:</p>
<ul>
<li>For instance, if we have a nil tree, then its height is a 0.</li>
<li>Otherwise, We're 1 plus the maximum of the left child tree and the right child tree.</li>
<li>So if we look at a leaf for example, that height would be 1 because the height of the left child is nil, is 0, and the height of the nil right child is also 0. So the max of that is 0, then 1 plus 0.</li>
</ul>
<h4 id="heading-heighttree-algorithm">Height(tree) algorithm</h4>
<pre><code><span class="hljs-keyword">if</span> tree = nil:
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> + Max(Height(tree.left),Height(tree.right))
</code></pre><h4 id="heading-here-is-the-code-in-c">Here is the code in C++</h4>
<pre><code>int maxDepth(struct node* node)
{
    <span class="hljs-keyword">if</span> (node==NULL)
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
   <span class="hljs-keyword">else</span>
   {
       int rDepth = maxDepth(node-&gt;right);
       int lDepth = maxDepth(node-&gt;left);

       <span class="hljs-keyword">if</span> (lDepth &gt; rDepth)
       {
           <span class="hljs-keyword">return</span>(lDepth+<span class="hljs-number">1</span>);
       }
       <span class="hljs-keyword">else</span>
       {
            <span class="hljs-keyword">return</span>(rDepth+<span class="hljs-number">1</span>);
       }
   }
}
</code></pre><p>We could also look at calculating the size of a tree that is the number of nodes.</p>
<ul>
<li>Again, if we have a nil tree, we have zero nodes.</li>
<li>Otherwise, we have the number of nodes in the left child plus 1 for ourselves plus the number of nodes in the right child. So 1 plus the size of the left tree plus the size of the right tree.</li>
</ul>
<h4 id="heading-sizetree-algorithm">Size(tree) algorithm</h4>
<pre><code><span class="hljs-keyword">if</span> tree = nil
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> + Size(tree.left) + Size(tree.right)
</code></pre><h4 id="heading-here-is-the-code-in-c-1">Here is the code in C++</h4>
<pre><code>int treeSize(struct node* node)
{
    <span class="hljs-keyword">if</span> (node==NULL)
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">else</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>+(treeSize(node-&gt;left) + treeSize(node-&gt;right));
}
</code></pre><h4 id="heading-traversal">Traversal</h4>
<p>There are 3 kinds of traversals that are done typically over a binary search tree. All these traversals have a somewhat common way of going over the nodes of the tree.</p>
<h5 id="heading-in-order">In-order</h5>
<p>This traversal first goes over the left subtree of the root node, then accesses the current node, followed by the right subtree of the current node. The code represents the base case too, which says that an empty tree is also a binary search tree.</p>
<pre><code><span class="hljs-keyword">void</span> inOrder(struct node* root) {
        <span class="hljs-comment">// Base case</span>
        <span class="hljs-keyword">if</span> (root == <span class="hljs-literal">null</span>) {
                <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-comment">// Travel the left sub-tree first.</span>
        inOrder(root.left);
        <span class="hljs-comment">// Print the current node value</span>
        printf(<span class="hljs-string">"%d "</span>, root.data);
        <span class="hljs-comment">// Travel the right sub-tree next.</span>
        inOrder(root.right);
}
</code></pre><h3 id="heading-pre-order">Pre-order</h3>
<p>This traversal first accesses the current node value, then traverses the left and right sub-trees respectively.</p>
<pre><code><span class="hljs-keyword">void</span> preOrder(struct node* root) {
        <span class="hljs-keyword">if</span> (root == <span class="hljs-literal">null</span>) {
                <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-comment">// Print the current node value</span>
        printf(<span class="hljs-string">"%d "</span>, root.data);
        <span class="hljs-comment">// Travel the left sub-tree first.</span>
        preOrder(root.left);
        <span class="hljs-comment">// Travel the right sub-tree next.</span>
        preOrder(root.right);
}
</code></pre><h3 id="heading-post-order">Post-order</h3>
<p>This traversal puts the root value at last, and goes over the left and right sub-trees first. The relative order of the left and right sub-trees remain the same. Only the position of the root changes in all the above mentioned traversals.</p>
<pre><code><span class="hljs-keyword">void</span> postOrder(struct node* root) {
        <span class="hljs-keyword">if</span> (root == <span class="hljs-literal">null</span>) {
                <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-comment">// Travel the left sub-tree first.</span>
        postOrder(root.left);
        <span class="hljs-comment">// Travel the right sub-tree next.</span>
        postOrder(root.right);
        <span class="hljs-comment">// Print the current node value</span>
        printf(<span class="hljs-string">"%d "</span>, root.data);
}
</code></pre><h3 id="heading-relevant-videos-on-freecodecamp-youtube-channel">Relevant videos on freeCodeCamp YouTube channel</h3>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5cU1ILGy6dM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-and-binary-search-tree-traversal-and-height">And Binary Search Tree: Traversal and Height</h2>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Aagf3RyK3Lw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h3 id="heading-following-are-common-types-of-binary-trees">Following are common types of Binary Trees:</h3>
<p>Full Binary Tree/Strict Binary Tree: A Binary Tree is full or strict if every node has exactly 0 or 2 children.</p>
<pre><code>          <span class="hljs-number">18</span>
         /   \
       /       \  
     <span class="hljs-number">15</span>         <span class="hljs-number">30</span>  
    /  \       /  \
  <span class="hljs-number">40</span>    <span class="hljs-number">50</span>   <span class="hljs-number">100</span>   <span class="hljs-number">40</span>
</code></pre><p>In Full Binary Tree, number of leaf nodes is equal to number of internal nodes plus one.</p>
<p>Complete Binary Tree: A Binary Tree is complete Binary Tree if all levels are completely filled except possibly the last level and the last level has all keys as left as possible</p>
<pre><code>           <span class="hljs-number">18</span>
         /    \
       /        \  
     <span class="hljs-number">15</span>         <span class="hljs-number">30</span>  
    /  \       /  \
  <span class="hljs-number">40</span>    <span class="hljs-number">50</span>   <span class="hljs-number">100</span>   <span class="hljs-number">40</span>
 /  \   /
<span class="hljs-number">8</span>    <span class="hljs-number">7</span> <span class="hljs-number">9</span>
</code></pre><p>Perfect Binary Tree A Binary tree is Perfect Binary Tree in which all internal nodes have two children and all leaves are at the same level.</p>
<pre><code>          <span class="hljs-number">18</span>
         /  \
       /      \  
     <span class="hljs-number">15</span>        <span class="hljs-number">30</span>  
    /  \      /  \
  <span class="hljs-number">40</span>    <span class="hljs-number">50</span>  <span class="hljs-number">100</span>   <span class="hljs-number">40</span>
</code></pre><h3 id="heading-augmenting-a-bst">Augmenting a BST</h3>
<p>Sometimes we need to store some additional information with the traditional data structures to make our tasks easier. For example, consider a scenario where you are supposed to find the ith smallest number in a set. You can use brute force here but we can reduce the complexity of the problem to <code>O(lg n)</code> by augmenting a red-black or any self-balancing tree (where n is the number of elements in the set). We can also compute rank of any element in <code>O(lg n)</code> time. Let us consider a case where we are augmenting a red-black tree to store the additional information needed. Besides the usual attributes, we can store number of internal nodes in the subtree rooted at x(size of the subtree rooted at x including the node itself). Let x be any arbitrary node of a tree.</p>
<p><code>x.size = x.left.size + x.right.size + 1</code></p>
<p>While augmenting the tree, we should keep in mind, that we should be able to maintain the augmented information as well as do other operations like insertion, deletion, updating in <code>O(lg n)</code> time.</p>
<p>Since, we know that the value of x.left.size will give us the number of nodes which proceed x in the order traversal of the tree. Thus, <code>x.left.size + 1</code> is the rank of x within the subtree rooted at x.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tree Traversals explained: They’re like a class of lazy students trying to cheat on their exam ]]>
                </title>
                <description>
                    <![CDATA[ By Sachin Malhotra Imagine that you are enrolled in a math class at one of the most prestigious universities of the world. You have an exam coming up real soon. Obviously, you want to perform well on the exam. The thing about this university is that ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tree-traversals-explained-theyre-like-a-class-of-lazy-students-trying-to-cheat-on-their-exam-b46563211427/</link>
                <guid isPermaLink="false">66c3639bc6c49ae59cf21b22</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Trees ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 14 Feb 2018 11:48:22 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*tCYpJPPIECnHUWw9BR_vrg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sachin Malhotra</p>
<p>Imagine that you are enrolled in a math class at one of the most prestigious universities of the world.</p>
<p>You have an exam coming up real soon. Obviously, you want to perform well on the exam.</p>
<p>The thing about this university is that it has a clumsy set of professors. So cheating is really simple. You can easily copy from the guy sitting behind and ahead without getting caught.</p>
<p>The professors, in order to take control of this problem, came up with two solutions:</p>
<ul>
<li>The number of students sitting in a class is never fixed. And the people sitting in one class taking the test change from one test to another.</li>
<li>The seating arrangement is released five minutes before the exam. The seating arrangement is alphabetical. But since the students are never fixed and new ones may get added or old ones removed from a class randomly, the arrangement has to be explicitly released for the students to know where exactly they have to sit.</li>
</ul>
<p>Say you’re one of those lazy students who wants to cheat, despite the consequences. Five minutes before the exam when the seating arrangement is released, how do you find out who is sitting in front of you and who’s behind as quickly as possible?</p>
<p>You won’t be able to cheat if you don’t talk to these two people beforehand and strategize, right?</p>
<h3 id="heading-the-seating-arrangement">The Seating Arrangement</h3>
<p>So the professors released the seating arrangement for the first test ever conducted this way. Say it had N students. If these students were to remain the same from one test to another, then it would have been very easy to cheat, right? Because the seating arrangement is always done alphabetically.</p>
<p>Therefore, the professors keep on adding or removing students from this list from one test to another, and only released these modifications before each test. This way, students could never know deterministically before a test who would be sitting in front of or behind them.</p>
<p>Let’s consider this problem in algorithmic terms. We are given a list of N elements where elements in this case are student’s names. This list keeps on varying from one exam to another, such that new elements can be added to the list or existing elements can be removed from the list.</p>
<p>Given the list of modifications at any given time T and a name N, we need to determine the elements B and A, such that B would come right before N and A would come right after N if the list were to be sorted.</p>
<p>Now let’s look at what data structures are available to us and what would suit this problem the best.</p>
<h3 id="heading-oh-array-my-old-friend-will-you-help-me">Oh Array, my old friend, will you help me?</h3>
<p>Using an array seems to be a rather straightforward approach.</p>
<ul>
<li>We can simply put all the names on the released list in an array.</li>
<li>Then we sort all the names (the list of names released might be randomly arranged) lexicographically</li>
<li>And then we can find our name in the list by using a binary search procedure. This would give us the predecessor and the successor.</li>
</ul>
<p>This seems to be a viable approach to solve this problem. The issue at hand, however, is that the students are never fixed from one exam to another. And so the list that was released for the very first exam would vary dynamically when new students were added and old ones were removed.</p>
<p>We can sort the list for the very first time, and then keep on adding new elements and removing old ones accordingly moving forward.</p>
<p>However, the complexity of adding or removing an element from an array is of the order <code>O(n)</code> . Since the number of students could be very large, and we don’t know how many modifications there would be before some new test, this would take a lot of time and the test would start before we could solve the problem. Remember that the modifications are released just five minutes before the test.</p>
<p>So what other data structure do we have where insertion and deletion can be done very quickly?</p>
<h3 id="heading-hmmmm-maybe-linked-list-is-my-true-friend-after-all">Hmmmm, maybe Linked List is my true friend after all</h3>
<p>As far as a linked list is concerned, it has it’s own set of problems when dealing with this type of situation. Initially, we need to sort the list of elements lexicographically. Since this is a one-time operation, because it is only to be done for the first exam, the time taken here does not really matter.</p>
<p>From the next exam onwards, only the modifications are released. Adding or deleting an element from a linked list is a constant time operation, provided we know the location of that element in the list.</p>
<p>Finding an element in a linked list is a linear time operation — it takes <code>O(n)</code> . I know there are concepts like <a target="_blank" href="https://en.wikipedia.org/wiki/Skip_list">skip lists</a>, but why dive into something like this when we can solve this problem in a much better fashion by using another type of data structure?</p>
<h3 id="heading-enter-binary-search-trees-the-new-kid-in-town">Enter Binary Search Trees, the new kid in town</h3>
<p>Let’s look at how we can model our data using a binary search tree (BST). Then we’ll see how a BST can help us solve the problem we initially set out to solve.</p>
<p>A Binary Search Tree is basically a binary tree with a special way of ordering the nodes.</p>
<p><strong>For a node with key <em>k</em>, every key in the left subtree is less than <em>k</em> and every key in the right subtree is greater than <em>k</em>.</strong></p>
<p>In our case, the keys will be the names of the students.</p>
<p>Consider the following example to see how a binary search tree is constructed. This should lend greater clarity to the data structure.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*fvAa2lIvPcl3pEF0EwjT_g.png" alt="Image" width="800" height="933" loading="lazy">
_[http://btechsmartclass.com/DS/images/BST%20Construction.png](http://btechsmartclass.com/DS/images/BST%20Construction.png" rel="noopener" target="<em>blank" title=")</em></p>
<p>Constructing a Binary Search Tree is not enough. We need to make sure it is <a target="_blank" href="http://www.stoimen.com/blog/2012/07/03/computer-algorithms-balancing-a-binary-search-tree/">balanced</a>. The reason we say that a Binary Search Tree needs to be balanced is that, if it is not balanced, then we can have something like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*4rHcryjV-ySjXORcxzqQeA.png" alt="Image" width="800" height="892" loading="lazy">
<em>A left skewed binary search tree.</em></p>
<p>This is known as a skewed binary search tree. If such a thing happens, then the BST basically transforms into a linked list and that is of no use to us. Therefore, we have this notion of keeping a BST balanced so that we don’t run into this problem.</p>
<p>The notion of balanced is defined differently by different approaches, like Red Black Trees or AVL trees. Further explanation of these trees is out of the scope of this article.</p>
<p>Coming back to arranging our data in a balanced BST: the keys to our BST would be the names of the students, and lexicographic matching would be used to determine the structure of the BST.</p>
<p>Suppose that there were a million students taking the test. If our binary search tree is balanced, then the complexity of performing any operation is upper bounded by <code>O(log(n))</code> . <strong>Hence, for 1 million nodes, the maximum number of nodes to be scanned would be just 14.</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*WX_no1yjkuvyro78viF21w.png" alt="Image" width="800" height="600" loading="lazy"></p>
<p>That’s a lot of complexity reduction simply by arranging the data in a certain manner. That is the advantage of representing data in a <strong>balanced</strong> Binary Search Tree.</p>
<p>The main problem with the array-based approach was that we could not efficiently insert or delete an element from the array. And the problem with the linked list approach was that there was no efficient way for us to find an element in the linked list even if it were sorted.</p>
<p>As for a balanced binary search tree, the time complexity to insert, delete, or search for an element is all bounded by <code>O(log(n))</code> . And this is precisely what makes this data structure extremely exciting.</p>
<p>However, we still haven’t solved our original problem. Given the name of a student, we want to find out the student sitting right behind and right in front of them. This boils down to finding the <strong>in-order successor and predecessor in the given Binary Search Tree.</strong></p>
<h3 id="heading-in-order-traversal-and-sorted-order-in-a-bst">In-order Traversal and Sorted Order in a BST</h3>
<p>An interesting property of the binary search trees is that we can retrieve the elements in the sorted order (even reverse) by doing an in-order traversal over the binary search tree.</p>
<p>So the in-order successor of a node X is the element that comes right after X in the in-order traversal over the given BST. For our cheating problem, this in-order successor would be the student sitting in front of us.</p>
<p>The in-order predecessor of a node X is the element that comes right before X in the in-order traversal (or the element that comes right after X in the <strong>reverse</strong> in-order traversal) over the given BST. For our cheating problem, this in-order predecessor would be the student sitting right behind us.</p>
<h3 id="heading-in-order-successor-in-a-bst">In-order Successor in a BST</h3>
<p>There are two different cases that we need to handle when finding the in-order successor of a node in a BST.</p>
<p><strong>The first case</strong> is when the right child exists for the node whose in-order successor we are trying to find. Consider the following example.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HT_4eHf-yWORRyajZGfbqg.png" alt="Image" width="800" height="750" loading="lazy"></p>
<p>Here we wanted to find the in-order successor of the highlighted node 8. Since it has a right child, the <strong>in-order successor would be the leftmost node in the tree with a right child, or 15 as the root</strong>. So that node would be 10 in this case.</p>
<p><strong>The second case</strong> is when there is no right child.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*z6Q879IxNa5B6jRC6s1CaQ.png" alt="Image" width="800" height="560" loading="lazy"></p>
<p>In this case, the in-order successor has two possibilities:</p>
<ol>
<li>One is where the node under consideration is the left child of its parent. In this case, the in-order successor would be the parent itself. So for our given case, the in-order successor would be 10.</li>
<li>The second case is when the current node is the right child of it’s parent. And it doesn’t have a right child. So it is the rightmost node in the BST and it has no in-order successor.</li>
</ol>
<p>Handling the first case is fairly simple for a binary search tree. For the second case, where the given node does not have a right child (or any parent pointers), we will have to rely on our good ol’ recursion mechanism and do an in-order traversal until we figure out the parent of our given node.</p>
<p>So, the worst case complexity can be O(n) if the case above occurs.</p>
<p>Using this algorithm, we can quickly find out the student who will be sitting right in front of us in the exam.</p>
<h3 id="heading-in-order-predecessor-in-a-bst">In-order Predecessor in a BST</h3>
<p>This is the exact reverse of the previous case.</p>
<p>Again, we need to handle two different cases when finding the in-order predecessor of a node in a BST. Look at the following diagrams and try to relate the two cases being referred to here.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*8LEzigzWixE_psr5BDeqdA.png" alt="Image" width="800" height="669" loading="lazy"></p>
<p>This is the case where the node has a left child. We need to find the rightmost child of the tree rooted at this left child — the rightmost node in the tree rooted at 2.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*MXJ1lCqihi0bmcfelm5WFA.png" alt="Image" width="800" height="635" loading="lazy"></p>
<p>No left child. So we need to find the parent.</p>
<p>If you look closely, I’ve just reversed the order of traversal here and the rest of the code is the same as before. (NOTE: this code is used when there is no left child of the node for which we want to find the in-order predecessor).</p>
<p><strong>In-order predecessor becomes the reverse in-order successor.</strong></p>
<p>Well now that you know how you should arrange the class seating arrangement list, go get some solid marks ???. Just kidding!! Cheating is bad — don’t ever do it!</p>
<p>Hope you got the main idea behind the different usages for data structures and how to find the in-order successor and predecessor in a BST.</p>
<p>EDIT: Kudos to <a target="_blank" href="https://www.freecodecamp.org/news/tree-traversals-explained-theyre-like-a-class-of-lazy-students-trying-to-cheat-on-their-exam-b46563211427/undefined">Divya Godayal</a> for pointing out a set of major mistakes in the initial draft and also for ensuring that the article flows nicely :) :)</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
