<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: vakhnin</title>
    <description>The latest articles on Forem by vakhnin (@vakhnin).</description>
    <link>https://forem.com/vakhnin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3559249%2Ff0e9d734-9e7b-4f6c-b6b7-73b843a22ba4.jpeg</url>
      <title>Forem: vakhnin</title>
      <link>https://forem.com/vakhnin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vakhnin"/>
    <language>en</language>
    <item>
      <title>The Vakhnin Algorithm: Left-Side Tree Traversal with O(1) Memory</title>
      <dc:creator>vakhnin</dc:creator>
      <pubDate>Sun, 12 Oct 2025 05:26:26 +0000</pubDate>
      <link>https://forem.com/vakhnin/the-vakhnin-algorithm-left-side-tree-traversal-with-o1-memory-13g0</link>
      <guid>https://forem.com/vakhnin/the-vakhnin-algorithm-left-side-tree-traversal-with-o1-memory-13g0</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The Vakhnin Algorithm: Left-Side Tree Traversal with O(1) Memory&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Elements of the Tree&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Terminator (T)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Terminator&lt;/strong&gt; is the last node in a subtree encountered during the left-side traversal.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Parent of the Next Subtree (PNS)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;PNS&lt;/strong&gt; is the node to which the algorithm returns after finishing the traversal of the left subtree.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Pointer to the Current PNS&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A pointer that temporarily stores a reference to &lt;strong&gt;PNS&lt;/strong&gt; in order to ensure the transition to the right subtree.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Marker Node (M)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;M&lt;/strong&gt; is a service node written into the right pointer of &lt;strong&gt;T&lt;/strong&gt; to mark the end of the current subtree.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Searching for the Terminator&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The search for &lt;strong&gt;T&lt;/strong&gt; starts from the root of a subtree. The algorithm moves through the tree as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the current node has a &lt;strong&gt;right branch&lt;/strong&gt;, move to its child.
&lt;/li&gt;
&lt;li&gt;If there is no right branch, move to the &lt;strong&gt;left branch&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;If the node has &lt;strong&gt;no children&lt;/strong&gt; (both pointers are empty), this node is the &lt;strong&gt;Terminator (T)&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tree Diagram with Terminator and Service Elements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnshrtdzlapax9zoxgvyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnshrtdzlapax9zoxgvyz.png" alt="Tree diagram with Terminator and service elements" width="295" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step-by-Step Process of Searching for the Terminator&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Start from the root of the subtree (&lt;code&gt;5&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Move to the right child (&lt;code&gt;7&lt;/code&gt;), since the current node has a right branch.
&lt;/li&gt;
&lt;li&gt;Node &lt;code&gt;7&lt;/code&gt; has no right branch, but it has a left one. Move to the left child (&lt;code&gt;9&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Node &lt;code&gt;9&lt;/code&gt; has both children. Move to the right child (&lt;code&gt;6&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Node &lt;code&gt;6&lt;/code&gt; has no children (both pointers are empty) — this is the &lt;strong&gt;Terminator (T)&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting and Resetting Terminator Links&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;At the first visit (setting links):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Right pointer&lt;/strong&gt;: redirected to &lt;strong&gt;M&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left pointer&lt;/strong&gt;: redirected to the &lt;strong&gt;pointer to the current PNS&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;At the second visit (resetting links):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Left and right pointers are restored to their initial state (set to empty).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Traversal Algorithm&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Initialization&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setting the initial node:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The algorithm starts from the root of the tree, which becomes the current node for processing.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pointer to the current parent of the next subtree (PNS):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This pointer is initially empty. Transitioning to this empty pointer signals the end of the algorithm.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creating the Marker Node:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;Marker Node&lt;/strong&gt; is used to mark the end of the current subtree (&lt;strong&gt;T&lt;/strong&gt;) and helps manage the return to &lt;strong&gt;PNS&lt;/strong&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Traversal Process&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For each node:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process the node by adding its value to the result.
&lt;/li&gt;
&lt;li&gt;If the node has only one child, move to it.
&lt;/li&gt;
&lt;li&gt;If the node has &lt;strong&gt;both children&lt;/strong&gt;, or if the node is &lt;strong&gt;T after a service pass&lt;/strong&gt;
(after the service pass, &lt;strong&gt;T&lt;/strong&gt; has both pointers non-empty):

&lt;ul&gt;
&lt;li&gt;If the node is &lt;strong&gt;T after a service pass&lt;/strong&gt;:
&lt;/li&gt;
&lt;li&gt;Recognized by the presence of &lt;strong&gt;M&lt;/strong&gt; in its right pointer.
&lt;/li&gt;
&lt;li&gt;Save the left pointer, which stores the &lt;strong&gt;pointer to the current PNS&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Reset both left and right pointers to empty.
&lt;/li&gt;
&lt;li&gt;Continue the algorithm from the &lt;strong&gt;PNS&lt;/strong&gt; saved in the left pointer.
&lt;/li&gt;
&lt;li&gt;If the node is not &lt;strong&gt;T&lt;/strong&gt;:
&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;T&lt;/strong&gt; in the left subtree of the current node.
&lt;/li&gt;
&lt;li&gt;Write the &lt;strong&gt;Marker Node (M)&lt;/strong&gt; into the right pointer of the found &lt;strong&gt;T&lt;/strong&gt; to mark the end of the current subtree.
&lt;/li&gt;
&lt;li&gt;Write the current &lt;strong&gt;PNS&lt;/strong&gt; into the left pointer of the found &lt;strong&gt;T&lt;/strong&gt; to ensure the return after finishing the left subtree traversal.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;State After Traversal&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;All nodes of the tree are processed.
&lt;/li&gt;
&lt;li&gt;Left and right pointers of all &lt;strong&gt;T&lt;/strong&gt; nodes are restored to their original state.
&lt;/li&gt;
&lt;li&gt;All service elements, such as markers and temporary links, are removed.
&lt;/li&gt;
&lt;li&gt;The tree structure is fully restored and identical to its initial state.
&lt;/li&gt;
&lt;li&gt;The traversal result is represented as a sequence of node values corresponding to the full left-side traversal.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Python Implementation of Full Left-Side Traversal of a Binary Tree&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Processes a tree node by adding its value to the global path list.
&lt;/span&gt;    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;traverse_tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Performs a custom traversal of the tree using markers.
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Finds the terminator — the rightmost node in the subtree
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;

    &lt;span class="n"&gt;marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Marker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;process_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Second visit to the terminator
&lt;/span&gt;            &lt;span class="n"&gt;root_right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;  &lt;span class="c1"&gt;# Save the root of the right subtree
&lt;/span&gt;            &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# Break the service link (marker)
&lt;/span&gt;            &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# Break the link to the right subtree
&lt;/span&gt;            &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root_right&lt;/span&gt;  &lt;span class="c1"&gt;# Move to process the right subtree
&lt;/span&gt;        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;terminator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_terminator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;terminator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;  &lt;span class="c1"&gt;# Set the marker
&lt;/span&gt;            &lt;span class="n"&gt;terminator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;  &lt;span class="c1"&gt;# Save the link to the right subtree
&lt;/span&gt;            &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Full version of the code with tests available on GitHub Gist:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/vakhnin/eec8ffd925a5e382a8403c9256e28934" rel="noopener noreferrer"&gt;Vakhnin Algorithm - Full Implementation with Tests&lt;/a&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
