Open In App

Succinct Encoding of Binary Tree

Last Updated : 22 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

A succinct encoding of Binary Tree takes close to minimum possible space. The number of structurally different binary trees on n nodes is n’th Catalan number. For large n, this is about 4n; thus we need at least about log2 4 n = 2n bits to encode it. A succinct binary tree therefore would occupy 2n+o(n) bits.

One simple representation which meets this bound is to visit the nodes of the tree in preorder, outputting “1” for an internal node and “0” for a leaf. If the tree contains data, we can simply simultaneously store it in a consecutive array in preorder.

Below is algorithm for encoding: 

function EncodeSuccinct(node n, bitstring structure, array data) {
    if n = nil then
        append 0 to structure;
    else
        append 1 to structure;
        append n.data to data;
        EncodeSuccinct(n.left, structure, data);
        EncodeSuccinct(n.right, structure, data);
}

And below is algorithm for decoding 

function DecodeSuccinct(bitstring structure, array data) {
    remove first bit of structure and put it in b
    if b = 1 then
        create a new node n
        remove first element of data and put it in n.data
        n.left = DecodeSuccinct(structure, data)
        n.right = DecodeSuccinct(structure, data)
        return n
    else
        return nil
}

Example: 

Input:   
        10
     /      \
   20       30
  /  \        \
 40   50      70 

Data Array (Contains preorder traversal)
10 20 40 50 30 70

Structure Array
1 1 1 0 0 1 0 0 1 0 1 0 0 
1 indicates data and 0 indicates NULL

Below is the implementation of above algorithms.

C++




// C++ program to demonstrate Succinct Tree Encoding and decoding
#include<bits/stdc++.h>
using namespace std;
 
// A Binary Tree Node
struct Node
{
    int key;
    struct Node* left, *right;
};
 
// Utility function to create new Node
Node *newNode(int key)
{
    Node *temp = new Node;
    temp->key  = key;
    temp->left  = temp->right = NULL;
    return (temp);
}
 
// This function fills lists 'struc' and 'data'.  'struc' list
// stores structure information. 'data' list stores tree data
void EncodeSuccinct(Node *root, list<bool> &struc, list<int> &data)
{
    // If root is NULL, put 0 in structure array and return
    if (root == NULL)
    {
        struc.push_back(0);
        return;
    }
 
    // Else place 1 in structure array, key in 'data' array
    // and recur for left and right children
    struc.push_back(1);
    data.push_back(root->key);
    EncodeSuccinct(root->left, struc, data);
    EncodeSuccinct(root->right, struc, data);
}
 
// Constructs tree from 'struc' and 'data'
Node *DecodeSuccinct(list<bool> &struc, list<int> &data)
{
    if (struc.size() <= 0)
        return NULL;
 
    // Remove one item from structure list
    bool b = struc.front();
    struc.pop_front();
 
    // If removed bit is 1,
    if (b == 1)
    {
         // remove an item from data list
        int key = data.front();
        data.pop_front();
 
        // Create a tree node with the removed data
        Node *root = newNode(key);
 
        // And recur to create left and right subtrees
        root->left = DecodeSuccinct(struc, data);
        root->right = DecodeSuccinct(struc, data);
        return root;
    }
 
    return NULL;
}
 
// A utility function to print tree
void preorder(Node* root)
{
    if (root)
    {
        cout << "key: "<< root->key;
        if (root->left)
            cout << " | left child: " << root->left->key;
        if (root->right)
            cout << " | right child: " << root->right->key;
        cout << endl;
        preorder(root->left);
        preorder(root->right);
    }
}
 
// Driver program
int main()
{
    // Let us construct the Tree shown in the above figure
    Node *root         = newNode(10);
    root->left         = newNode(20);
    root->right        = newNode(30);
    root->left->left   = newNode(40);
    root->left->right  = newNode(50);
    root->right->right = newNode(70);
 
    cout << "Given Tree\n";
    preorder(root);
    list<bool> struc;
    list<int>  data;
    EncodeSuccinct(root, struc, data);
 
    cout << "\nEncoded Tree\n";
    cout << "Structure List\n";
    list<bool>::iterator si; // Structure iterator
    for (si = struc.begin(); si != struc.end(); ++si)
        cout << *si << " ";
 
    cout << "\nData List\n";
    list<int>::iterator di; // Data iterator
    for (di = data.begin(); di != data.end(); ++di)
        cout << *di << " ";
 
    Node *newroot = DecodeSuccinct(struc, data);
 
    cout << "\n\nPreorder traversal of decoded tree\n";
    preorder(newroot);
 
    return 0;
}


Java




// Java program to demonstrate Succinct
// Tree Encoding and decoding
import java.util.*;
 
class GFG{
 
// A Binary Tree Node
static class Node
{
    int key;
    Node left, right;
};
 
// Utility function to create new Node
static Node newNode(int key)
{
    Node temp = new Node();
    temp.key  = key;
    temp.left  = temp.right = null;
    return (temp);
}
 
static Vector<Boolean> struc;
static Vector<Integer> data;
static Node root;
 
// This function fills lists 'struc' and
// 'data'. 'struc' list stores structure
// information. 'data' list stores tree data
static void EncodeSuccinct(Node root)
{
     
    // If root is null, put 0 in
    // structure array and return
    if (root == null)
    {
        struc.add(false);
        return;
    }
 
    // Else place 1 in structure array,
    // key in 'data' array and recur
    // for left and right children
    struc.add(true);
    data.add(root.key);
    EncodeSuccinct(root.left);
    EncodeSuccinct(root.right);
}
 
// Constructs tree from 'struc' and 'data'
static Node DecodeSuccinct()
{
    if (struc.size() <= 0)
        return null;
 
    // Remove one item from structure list
    boolean b = struc.get(0);
    struc.remove(0);
 
    // If removed bit is 1,
    if (b == true)
    {
         
        // Remove an item from data list
        int key = data.get(0);
        data.remove(0);
 
        // Create a tree node with the
        // removed data
        Node root = newNode(key);
 
        // And recur to create left and
        // right subtrees
        root.left = DecodeSuccinct();
        root.right = DecodeSuccinct();
        return root;
    }
    return null;
}
 
// A utility function to print tree
static void preorder(Node root)
{
    if (root != null)
    {
        System.out.print("key: "+ root.key);
        if (root.left != null)
            System.out.print(" | left child: "
                             root.left.key);
        if (root.right != null)
            System.out.print(" | right child: "
                             root.right.key);
        System.out.println();
         
        preorder(root.left);
        preorder(root.right);
    }
}
 
// Driver code
public static void main(String[] args)
{
     
    // Let us construct Tree shown in
    // the above figure
    Node root = newNode(10);
    root.left = newNode(20);
    root.right = newNode(30);
    root.left.left = newNode(40);
    root.left.right = newNode(50);
    root.right.right = newNode(70);
 
    System.out.print("Given Tree\n");
    preorder(root);
    struc = new Vector<>();
    data = new Vector<>();
    EncodeSuccinct(root);
 
    System.out.print("\nEncoded Tree\n");
    System.out.print("Structure List\n");
  
    for(boolean  si : struc)
    {
        if (si == true)
            System.out.print(1 + " ");
        else
            System.out.print(0 + " ");
    }
 
    System.out.print("\nData List\n");
    for(int di : data)
        System.out.print(di + " ");
 
    Node newroot = DecodeSuccinct();
 
    System.out.print("\n\nPreorder traversal" +
                     "of decoded tree\n");
                      
    preorder(newroot);
}
}
 
// This code is contributed by aashish1995


Python3




# Python program to demonstrate Succinct Tree Encoding and Decoding
 
# Node structure
class Node:
    # Utility function to create new Node
    def __init__(self , key):
        self.key = key
        self.left = None
        self.right = None
 
def EncodeSuccinct(root , struc , data):
     
    # If root is None , put 0 in structure array and return
    if root is None :
        struc.append(0)
        return
 
    # Else place 1 in structure array, key in 'data' array
    # and recur for left and right children
    struc.append(1)
    data.append(root.key)
    EncodeSuccinct(root.left , struc , data)
    EncodeSuccinct(root.right , struc ,data)
     
 
# Constructs tree from 'struc' and 'data'
def DecodeSuccinct(struc , data):
    if(len(struc) <= 0):
        return None
     
    # Remove one item from structure list
    b = struc[0]
    struc.pop(0)
     
    # If removed bit is 1
    if b == 1:
        key = data[0]
        data.pop(0)
     
        #Create a tree node with removed data
        root = Node(key)
 
        #And recur to create left and right subtrees
        root.left = DecodeSuccinct(struc , data);
        root.right = DecodeSuccinct(struc , data);
        return root
 
    return None
 
 
def preorder(root):
    if root is not None:
        print ("key: %d" %(root.key),end=" ")
             
        if root.left is not None:
            print ("| left child: %d" %(root.left.key),end=" ")
        if root.right is not None:
            print ("| right child %d" %(root.right.key),end=" ")
        print ()
        preorder(root.left)
        preorder(root.right)
 
# Driver Program
root = Node(10)
root.left = Node(20)
root.right = Node(30)
root.left.left = Node(40)
root.left.right = Node(50)
root.right.right = Node(70)        
 
print ("Given Tree")
preorder(root)
struc = []
data = []
EncodeSuccinct(root , struc , data)
 
print ("\nEncoded Tree")
print ("Structure List")
 
for i in struc:
    print (i ,end=" ")
 
print ("\nDataList")
for value in data:
    print (value,end=" ")
 
newroot = DecodeSuccinct(struc , data)
 
print ("\n\nPreorder Traversal of decoded tree")
preorder(newroot)
 
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


C#




// C# program to demonstrate Succinct
// Tree Encoding and decoding
using System;
using System.Collections.Generic;
class GFG{
 
  // A Binary Tree Node
  public
    class Node
    {
      public
        int key;
      public
        Node left, right;
    };
 
  // Utility function to create new Node
  static Node newNode(int key)
  {
    Node temp = new Node();
    temp.key  = key;
    temp.left  = temp.right = null;
    return (temp);
  }
  static List<Boolean> struc;
  static List<int> data;
  static Node root;
 
  // This function fills lists 'struc' and
  // 'data'. 'struc' list stores structure
  // information. 'data' list stores tree data
  static void EncodeSuccinct(Node root)
  {
 
    // If root is null, put 0 in
    // structure array and return
    if (root == null)
    {
      struc.Add(false);
      return;
    }
 
    // Else place 1 in structure array,
    // key in 'data' array and recur
    // for left and right children
    struc.Add(true);
    data.Add(root.key);
    EncodeSuccinct(root.left);
    EncodeSuccinct(root.right);
  }
 
  // Constructs tree from 'struc' and 'data'
  static Node DecodeSuccinct()
  {
    if (struc.Count <= 0)
      return null;
 
    // Remove one item from structure list
    bool b = struc[0];
    struc.RemoveAt(0);
 
    // If removed bit is 1,
    if (b == true)
    {
 
      // Remove an item from data list
      int key = data[0];
      data.Remove(0);
 
      // Create a tree node with the
      // removed data
      Node root = newNode(key);
 
      // And recur to create left and
      // right subtrees
      root.left = DecodeSuccinct();
      root.right = DecodeSuccinct();
      return root;
    }
    return null;
  }
 
  // A utility function to print tree
  static void preorder(Node root)
  {
    if (root != null)
    {
      Console.Write("key: "+ root.key);
      if (root.left != null)
        Console.Write(" | left child: "
                      root.left.key);
      if (root.right != null)
        Console.Write(" | right child: "
                      root.right.key);
      Console.WriteLine();
      preorder(root.left);
      preorder(root.right);
    }
  }
 
  // Driver code
  public static void Main(String[] args)
  {
 
    // Let us construct Tree shown in
    // the above figure
    Node root = newNode(10);
    root.left = newNode(20);
    root.right = newNode(30);
    root.left.left = newNode(40);
    root.left.right = newNode(50);
    root.right.right = newNode(70);
    Console.Write("Given Tree\n");
    preorder(root);
    struc = new List<Boolean>();
    data = new List<int>();
    EncodeSuccinct(root);
    Console.Write("\nEncoded Tree\n");
    Console.Write("Structure List\n");
    foreach(bool  si in struc)
    {
      if (si == true)
        Console.Write(1 + " ");
      else
        Console.Write(0 + " ");
    }
 
    Console.Write("\nData List\n");
    foreach(int di in data)
      Console.Write(di + " ");
    Node newroot = DecodeSuccinct();
    Console.Write("\n\nPreorder traversal" +
                  "of decoded tree\n");                    
    preorder(newroot);
  }
}
 
// This code is contributed by gauravrajput1


Javascript




<script>
 
// Javascript program to demonstrate Succinct
// Tree Encoding and decoding
// A Binary Tree Node
class Node
{
  constructor()
  {
    this.key = 0;
    this.left = null;
    this.right = null;
  }
};
 
// Utility function to create new Node
function newNode(key)
{
  var temp = new Node();
  temp.key  = key;
  temp.left  = temp.right = null;
  return (temp);
}
 
var struc = [];
var data = [];
var root = null;
 
// This function fills lists 'struc' and
// 'data'. 'struc' list stores structure
// information. 'data' list stores tree data
function EncodeSuccinct(root)
{
 
  // If root is null, put 0 in
  // structure array and return
  if (root == null)
  {
    struc.push(false);
    return;
  }
   
  // Else place 1 in structure array,
  // key in 'data' array and recur
  // for left and right children
  struc.push(true);
  data.push(root.key);
  EncodeSuccinct(root.left);
  EncodeSuccinct(root.right);
}
 
// Constructs tree from 'struc' and 'data'
function DecodeSuccinct()
{
  if (struc.length <= 0)
    return null;
     
  // Remove one item from structure list
  var b = struc[0];
  struc.shift(0);
   
  // If removed bit is 1,
  if (b == true)
  {
   
    // Remove an item from data list
    var key = data[0];
    data.shift();
     
    // Create a tree node with the
    // removed data
    var root = newNode(key);
     
    // And recur to create left and
    // right subtrees
    root.left = DecodeSuccinct();
    root.right = DecodeSuccinct();
    return root;
  }
  return null;
}
 
// A utility function to print tree
function preorder(root)
{
  if (root != null)
  {
    document.write("key: "+ root.key);
    if (root.left != null)
      document.write(" | left child: "
                    root.left.key);
    if (root.right != null)
      document.write(" | right child: "
                    root.right.key);
    document.write("<br>");
    preorder(root.left);
    preorder(root.right);
  }
}
 
// Driver code
// Let us construct Tree shown in
// the above figure
var root = newNode(10);
root.left = newNode(20);
root.right = newNode(30);
root.left.left = newNode(40);
root.left.right = newNode(50);
root.right.right = newNode(70);
document.write("Given Tree<br>");
preorder(root);
struc = [];
data = [];
EncodeSuccinct(root);
document.write("<br>Encoded Tree<br>");
document.write("Structure List<br>");
for(var si of struc)
{
  if (si == true)
    document.write(1 + " ");
  else
    document.write(0 + " ");
}
document.write("<br>Data List<br>");
for(var di of data)
  document.write(di + " ");
var newroot = DecodeSuccinct();
document.write("<br><br>Preorder traversal" +
              "of decoded tree<br>");                    
preorder(newroot);
 
// This code is contributed by rrrtnx.
</script>


Output

Given Tree
key: 10 | left child: 20 | right child: 30
key: 20 | left child: 40 | right child: 50
key: 40
key: 50
key: 30 | right child: 70
key: 70

Encoded Tree
Structure List
1 1 1 0 0 1 0 0 1 0 1 0 0 
Data List
10 20 40 50 30 70 

Preorder traversal of decoded tree
key: 10 | left child: 20 | right child: 30
key: 20 | left child: 40 | right child: 50
key: 40
key: 50
key: 30 | right child: 70
key: 70

 Time complexity: O(n)  
Auxiliary space: O(n).



Previous Article
Next Article

Similar Reads

Complexity of different operations in Binary tree, Binary Search Tree and AVL tree
In this article, we will discuss the complexity of different operations in binary trees including BST and AVL trees. Before understanding this article, you should have a basic idea about Binary Tree, Binary Search Tree, and AVL Tree. The main operations in a binary tree are: search, insert and delete. We will see the worst-case time complexity of t
4 min read
Convert a Binary Tree into its Mirror Tree (Invert Binary Tree)
Given a binary tree, the task is to convert the binary tree into its Mirror tree. Mirror of a Binary Tree T is another Binary Tree M(T) with left and right children of all non-leaf nodes interchanged. Recommended PracticeMirror TreeTry It!The idea is to traverse recursively and swap the right and left subtrees after traversing the subtrees. Follow
15+ min read
Check if an encoding represents a unique binary string
Given an encoding of a binary string of length k, the task is to find if the given encoding uniquely identifies a binary string or not. The encoding has counts of contiguous 1s (separated by 0s). For example, encoding of 11111 is {5}, encoding of 01101010 is {2, 1, 1} and encoding of 111011 is {3, 2}. Examples : Input: encoding[] = {3, 3, 3} Length
6 min read
Maximum sub-tree sum in a Binary Tree such that the sub-tree is also a BST
Given a binary tree, the task is to print the maximum sum of nodes of a sub-tree which is also a Binary Search Tree.Examples: Input : 7 / \ 12 2 / \ \ 11 13 5 / / \ 2 1 38 Output:44 BST rooted under node 5 has the maximum sum 5 / \ 1 38 Input: 5 / \ 9 2 / \ 6 3 / \ 8 7 Output: 8 Here each leaf node represents a binary search tree also a BST with su
12 min read
Convert a Generic Tree(N-array Tree) to Binary Tree
Prerequisite: Generic Trees(N-array Trees) In this article, we will discuss the conversion of the Generic Tree to a Binary Tree. Following are the rules to convert a Generic(N-array Tree) to a Binary Tree: The root of the Binary Tree is the Root of the Generic Tree.The left child of a node in the Generic Tree is the Left child of that node in the B
13 min read
Convert a Binary Tree to Threaded binary tree | Set 1 (Using Queue)
We have discussed Threaded Binary Tree. The idea of threaded binary trees is to make inorder traversal faster and do it without stack and without recursion. In a simple threaded binary tree, the NULL right pointers are used to store inorder successor. Wherever a right pointer is NULL, it is used to store inorder successor. The following diagram sho
12 min read
Check whether a binary tree is a full binary tree or not | Iterative Approach
Given a binary tree containing n nodes. The problem is to check whether the given binary tree is a full binary tree or not. A full binary tree is defined as a binary tree in which all nodes have either zero or two child nodes. Conversely, there is no node in a full binary tree, which has only one child node. Examples: Input : 1 / \ 2 3 / \ 4 5 Outp
8 min read
Binary Tree to Binary Search Tree Conversion using STL set
Given a Binary Tree, convert it to a Binary Search Tree. The conversion must be done in such a way that keeps the original structure of the Binary Tree.This solution will use Sets of C++ STL instead of array-based solution. Examples: Example 1 Input: 10 / \ 2 7 / \ 8 4 Output: 8 / \ 4 10 / \ 2 7 Example 2 Input: 10 / \ 30 15 / \ 20 5 Output: 15 / \
12 min read
Check whether a given binary tree is skewed binary tree or not?
Given a Binary Tree check whether it is skewed binary tree or not. A skewed tree is a tree where each node has only one child node or none. Examples: Input : 5 / 4 \ 3 / 2 Output : Yes Input : 5 / 4 \ 3 / \ 2 4 Output : No The idea is to check if a node has two children. If node has two children return false, else recursively compute whether subtre
13 min read
Check if a binary tree is subtree of another binary tree using preorder traversal : Iterative
Given two binary trees S and T, the task is the check that if S is a subtree of the Tree T. For Example: Input: Tree T - 1 / \ 2 3 / \ / \ 4 5 6 7 Tree S - 2 / \ 4 5 Output: YES Explanation: The above tree is the subtree of the tree T, Hence the output is YES Approach: The idea is to traverse both the tree in Pre-order Traversal and check for each
11 min read
Article Tags :
Practice Tags :
three90RightbarBannerImg