Flatten a binary tree into linked list

Introduction

Each node in a binary tree has a maximum of two children, known as the left child and the right child, making it a hierarchical data structure. In order to convert a binary tree into a linked list, the tree nodes must be rearranged in a certain order to make a linear structure. This process is known as "flattening." The objective is to rearrange the nodes of a binary tree so that the tree's structure is maintained while creating a linked list. It is important to create the linked list in a certain order to facilitate simple traversal.

Flatten a binary tree into linked list

Method 1: Recursion

Using a depth-first traversal approach, the recursive method flattens a binary tree into a linked list by iteratively moving through the tree structure. The function looks for a base case at every stage, making sure to stop when a null node is detected. The approach maintains a reference to the right subtree before flattening the left subtree, which is essential for subsequent reattachment. The procedure is then repeated via a recursive call on the left subtree. The function flattens the left subtree and then moves it to the right of the current node by adjusting pointers. It flattens the original right subtree recursively and proceeds to the end of this new flattened subtree on the right. Because it is recursive, the whole binary tree is inspected, and the nodes are rearranged in a particular sequence to create a linked list. Recursion is elegant because it can decompose a complicated problem into smaller, more manageable subproblems, resulting in more concise and expressive code.

Code

Output:

Flatten a binary tree into linked list

Code Explanation

Binary Tree Node Definition

  • Outlines the structure of a binary tree node consisting of three elements: a pointer to the left and right children (left and right) and an integer value (val).

Flatten Function

  • It is mainly used to convert a binary tree into a linked list.
  • Accepts as input a pointer to the binary tree's root.

Base Case Verification

  • The function returns and serves as the recursion's base case if the current node (root) is NULL. By doing this, it is ensured that the recursion ends at the end of each branch.

Save Right Subtree

  • Retains a reference to the current node's right subtree (root->right). Reattachment at a later time requires this.

Left Flattening Subtree

  • To flatten the left subtree of the current node, recursively use flatten(root->left) on itself.

Transfer the Left Flattened Subtree to the Right

  • The flattened left subtree is moved (root->right = root->left) to the right of the current node.
  • To keep the linked list structure intact, set the left child to NULL.

Proceed to the Right, to the End of the Flattened Subtree

  • Using a while loop iteratively advances to the right end of the flattened subtree.

Original Right Subtree Flattening

  • The original right subtree is flattened recursively using flatten(rightSubtree)).

Join the End with the Flattened Right Subtree

  • (root -> right = rightSubtree) joins the flattened right subtree to the end of the current node.

Print Linked List Function

  • Defines the printList function, which prints the flattened linked list's values.
  • Accepts as input a pointer to the linked list's head.

Method 2: Stack

This approach uses an explicit stack to track the nodes as it traverses the graph. The root node is pushed into an empty stack that the algorithm has initialized. A node is removed from the stack at each iteration of a while loop, which runs until the stack is empty. If there is a stack, the right kid is pushed onto it first, and then the left child. Processing of the left child comes first, thanks to this arrangement. The technique simultaneously modifies pointers to link the current node to the appropriate child. The binary tree is flattened depth-first by explicitly managing the traversal order using the stack and modifying pointers accordingly. When recursion is undesirable, this approach is especially helpful because the explicit stack offers an organized approach to handle the traversal and flattening process sequentially.

Code

Output:

Flatten a binary tree into linked list

Code Explanation

Definition of a Binary Tree Node

  • Outlines the structure of a binary tree node consisting of three elements: a pointer to the left and right children (left and right) and an integer value (val).

Definition of Stack Node

  • Describes a structure for a stack node that has a pointer to the next stack node (next) and a pointer to a tree node (node).

Definition of Stack

  • Defines a single component stack structure, which is a pointer to the stack's top (top).

Initialization of Stack

  • By allocating memory for the stack structure and setting the top pointer to NULL, createStack() initializes an empty stack.

Empty Stack Check

  • When determining whether a stack is empty, isEmpty() looks to see if the top pointer is NULL.

Push Mechanism

  • A new node is added to the stack with push(). It creates a new stack node, allocates memory for it, sets its node to the given tree node, and modifies the top pointer appropriately.

Pop Function

  • pop() takes the top node out of the stack and returns it. It releases memory for the stack node, obtains the tree node of the top node, checks for an empty stack, and modifies the top pointer.

Flattening Mechanism

  • The primary function flatten() uses an iterative stack-based method to flatten a binary tree's root into a linked list.
  • After initializing an empty stack and adding the root, iteratively processes nodes while modifying pointers.

Method 3: Iterative without Stack

This technique implicitly simulates the functionality of a stack using a threaded binary tree architecture. It makes use of the Morris Traversal tree traversal method, which threads each node's rightmost child to its successor in the in-order traversal sequence, therefore changing the tree topology. The Morris Traversal is modified for flattening purposes so that it may traverse and flatten the tree at the same time, doing away with the requirement for a stack or other extra data structure. The algorithm moves through the tree quickly and accurately by creating threaded connections between nodes and modifying pointers along the way. This technique is distinguished by its constant space complexity, which renders it a memory-conserving and effective substitute for both recursive and stack-based methods.

Code

Output:

Flatten a binary tree into linked list

Code Explanation

Definition of a Binary Tree Node

  • Outlines the structure of a binary tree node consisting of three elements: a pointer to the left and right children (left and right) and an integer value (val).

Flatten Function

  • With the use of the threaded tree traversal method Morris Traversal, the flatten function alters the binary tree in place.
  • The technique searches the left subtree for the rightmost node for each node that has a left child. This process iterates across the tree nodes.
  • The left subtree is then attached to the right of the current node, and a threaded connection is formed by moving the right subtree to the right of the rightmost node.
  • The current node's left child has NULL assigned to it.

Main Function

  • A sample binary tree is built in the main function.
  • To use Morris Traversal to flatten the binary tree, the flatten function is called.
  • Traversing the flattened linked list yields the linearized structure of the original binary tree.

Deallocation of Memory

The allocated memory for the flattened linked list and the binary tree nodes is released by the while loop in the main function. Every node in the linked list is released as it moves through it.






Latest Courses