Open In App

Succinct Encoding of Binary Tree

Last Updated : 28 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A succinct encoding of Binary Tree takes close to the 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 4n = 2n bits to encode it. A succinct binary tree therefore would occupy 2n + O(n) bits.

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

Example: 

Input:

45

Output: 1 1 0 0 1 0 1 0 0
Explanation: 1 indicates data and 0 indicates NULL.

Approach for encoding binary tree – O(n) Time and O(n) Space

The idea is to perform pre-order traversal of the binary tree. If the node is null, then append ‘0’ to the string. Otherwise append ‘1’ to the string and push the node value into a data array. Return the string and data array.

Below is the implementation of above approach:

C++
// C++ program to encode a 
// binary tree.
#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;
    Node (int x) {
        data = x;
        left = nullptr;
        right = nullptr;
    }
};

// Recursive pre-order function to 
// encode a binary tree.
void encodeTreeRecur(Node* root, string &s,
                     vector<int> &arr) {
    
    // For null nodes
    if (root == nullptr) {
        s.push_back('0');
        return;
    }
    
    s.push_back('1');
    
    // Store pre-order in array.
    arr.push_back(root->data);
    
    // Apply pre-order to left and 
    // right subtree.
    encodeTreeRecur(root->left, s, arr);
    encodeTreeRecur(root->right, s, arr);
}

pair<string, vector<int>> encodeTree(Node* root) {
    string s = "";
    vector<int> arr;
    
    encodeTreeRecur(root, s, arr);
    
    return make_pair(s, arr);
}

int main() {
    
    // Binary tree 
    //           10
    //        /     \  
    //      20       30  
    //     /  \        \
    //   40    50       70
    Node* root = new Node(10);     
    root->left = new Node(20);          
    root->right = new Node(30);         
    //root->left->left = new Node(40);   
    //root->left->right = new Node(50);  
    root->right->right = new Node(70);  

    pair<string, vector<int>> ans = encodeTree(root);
    
    cout << ans.first << endl;
    for (auto num: ans.second) 
        cout << num << " ";
    cout << endl;
    
    return 0;
}
Java
// Java program to encode a 
// binary tree.
import java.util.ArrayList;
import java.util.List;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class Pair {
    String s;
    ArrayList<Integer> arr;
    Pair(String s1, ArrayList<Integer> arr1) {
        s = s1;
        arr = arr1;
    }
}


class GfG {

    // Recursive pre-order function to 
    // encode a binary tree.
    static void encodeTreeRecur(Node root, 
	StringBuilder s, ArrayList<Integer> arr) {
        
        // For null nodes
        if (root == null) {
            s.append('0');
            return;
        }
        
        s.append('1');
        
        // Store pre-order in array.
        arr.add(root.data);
        
        // Apply pre-order to left and 
        // right subtree.
        encodeTreeRecur(root.left, s, arr);
        encodeTreeRecur(root.right, s, arr);
    }

    static Pair encodeTree(Node root) {
        StringBuilder s = new StringBuilder();
        ArrayList<Integer> arr = new ArrayList<>();
        
        encodeTreeRecur(root, s, arr);
        
        return new Pair(s.toString(), arr);
    }

    public static void main(String[] args) {
        
        // Binary tree 
        //           10
        //        /     \  
        //      20       30  
        //     /  \        \
        //   40    50       70
        Node root = new Node(10);     
        root.left = new Node(20);          
        root.right = new Node(30);         
        root.left.left = new Node(40);   
        root.left.right = new Node(50);  
        root.right.right = new Node(70);  

        Pair ans = encodeTree(root);
        
        System.out.println(ans.s);
        for (int num : ans.arr) 
            System.out.print(num + " ");
        System.out.println();
    }
}
Python
# Python program to encode a 
# binary tree.

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Recursive pre-order function to 
# encode a binary tree.
def encodeTreeRecur(root, s, arr):
    
    # For null nodes
    if root is None:
        s.append('0')
        return
    
    s.append('1')
    
    # Store pre-order in array.
    arr.append(root.data)
    
    # Apply pre-order to left and 
    # right subtree.
    encodeTreeRecur(root.left, s, arr)
    encodeTreeRecur(root.right, s, arr)

def encodeTree(root):
    s = []
    arr = []
    
    encodeTreeRecur(root, s, arr)
    
    return ''.join(s), arr

if __name__ == "__main__":
    
    # Binary tree 
    #           10
    #        /     \  
    #      20       30  
    #     /  \        \
    #   40    50       70
    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)

    ans = encodeTree(root)
    
    print(ans[0])
    for num in ans[1]:
        print(num, end=" ")
    print()
C#
// C# program to encode a 
// binary tree.
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {

    // Recursive pre-order function to 
    // encode a binary tree.
    static void encodeTreeRecur(Node root, 
					ref string s, List<int> arr) {
        
        // For null nodes
        if (root == null) {
            s += '0';
            return;
        }
        
        s += '1';
        
        // Store pre-order in array.
        arr.Add(root.data);
        
        // Apply pre-order to left and 
        // right subtree.
        encodeTreeRecur(root.left, ref s, arr);
        encodeTreeRecur(root.right, ref s, arr);
    }

    static Tuple<string, List<int>> encodeTree(Node root) {
        string s = "";
        List<int> arr = new List<int>();
        
        encodeTreeRecur(root, ref s, arr);
        
        return new Tuple<string, List<int>>(s, arr);
    }

    static void Main(string[] args) {
        
        // Binary tree 
        //           10
        //        /     \  
        //      20       30  
        //     /  \        \
        //   40    50       70
        Node root = new Node(10);     
        root.left = new Node(20);          
        root.right = new Node(30);         
        root.left.left = new Node(40);   
        root.left.right = new Node(50);  
        root.right.right = new Node(70);  

        Tuple<string, List<int>> ans = 
          					encodeTree(root);
        
        Console.WriteLine(ans.Item1);
        foreach (int num in ans.Item2) 
            Console.Write(num + " ");
        Console.WriteLine();
    }
}
JavaScript
// JavaScript program to encode a 
// binary tree.

class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Recursive pre-order function to 
// encode a binary tree.
function encodeTreeRecur(root, s, arr) {
    
    // For null nodes
    if (root === null) {
        s.push('0');
        return;
    }
    
    s.push('1');
    
    // Store pre-order in array.
    arr.push(root.data);
    
    // Apply pre-order to left and 
    // right subtree.
    encodeTreeRecur(root.left, s, arr);
    encodeTreeRecur(root.right, s, arr);
}

function encodeTree(root) {
    let s = [];
    let arr = [];
    
    encodeTreeRecur(root, s, arr);
    
    return [s.join(''), arr];
}

// Binary tree 
//           10
//        /     \  
//      20       30  
//     /  \        \
//   40    50       70
let root = new Node(10);
root.left = new Node(20);
root.right = new Node(30);
root.left.left = new Node(40);
root.left.right = new Node(50);
root.right.right = new Node(70);

const ans = encodeTree(root);

console.log(ans[0]);
console.log(ans[1].join(" "));

Output
1110010010100
10 20 40 50 30 70 

Approach for decoding binary tree – O(n) Time and O(n) Space

The idea is to perform pre-order traversal of the string. If the current character is ‘0’, return null. Otherwise create a new node with value equal to current element of the data array. Return the root node.

Below is the implementation of the above approach:

C++
// C++ program to decode a 
// binary tree.
#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;
    Node (int x) {
        data = x;
        left = nullptr;
        right = nullptr;
    }
};

// Recursive pre-order function to 
// decode a binary tree.
Node* decodeTreeRecur(int &i, string &s, int &j, vector<int> &arr) {
    
    // if s[i]==0, return null node
    if (s[i] == '0') {
        i++;
        return nullptr;
    }
    
    // Create a new Node
    Node* root = new Node(arr[j++]);
    i++;
    
    // Construct left and right subtree.
    root->left = decodeTreeRecur(i,s,j,arr);
    root->right = decodeTreeRecur(i,s,j,arr);
    
    return root;
}

Node* decodeTree(string s, vector<int> arr) {
    int i = 0, j = 0;
    return decodeTreeRecur(i, s, j, arr);
}

void printInorder(Node* root) {
    if (root == nullptr) return;
    printInorder(root->left);
    cout << root->data << " ";
    printInorder(root->right);
}

int main() {
    
    string s = "1110010010100";
    vector<int> arr = {10, 20, 40, 50, 30, 70};
    
    Node* root = decodeTree(s, arr);
    printInorder(root);
    return 0;
}
Java
// Java program to decode a 
// binary tree.
import java.util.ArrayList;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {

    // Recursive pre-order function to 
    // decode a binary tree.
    static Node decodeTreeRecur(int[] i, String s, 
				int[] j, ArrayList<Integer> arr) {
        
        // if s[i]==0, return null node
        if (s.charAt(i[0]) == '0') {
            i[0]++;
            return null;
        }
        
        // Create a new Node
        Node root = new Node(arr.get(j[0]++));
        i[0]++;
        
        // Construct left and right subtree.
        root.left = decodeTreeRecur(i, s, j, arr);
        root.right = decodeTreeRecur(i, s, j, arr);
        
        return root;
    }

    static Node decodeTree(String s, 
                           	ArrayList<Integer> arr) {
        int[] i = {0}, j = {0};
        return decodeTreeRecur(i, s, j, arr);
    }

    static void printInorder(Node root) {
        if (root == null) return;
        printInorder(root.left);
        System.out.print(root.data + " ");
        printInorder(root.right);
    }

    public static void main(String[] args) {
        
        String s = "1110010010100";
        ArrayList<Integer> arr = new ArrayList<>();
        arr.add(10);
      	arr.add(20);
      	arr.add(40);
      	arr.add(50);
      	arr.add(30);
      	arr.add(70);
        
        Node root = decodeTree(s, arr);
        printInorder(root);
    }
}
Python
# Python program to decode a 
# binary tree.

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Recursive pre-order function to 
# decode a binary tree.
def decodeTreeRecur(i, s, j, arr):
    
    # if s[i]==0, return null node
    if s[i[0]] == '0':
        i[0] += 1
        return None
    
    # Create a new Node
    root = Node(arr[j[0]])
    j[0] += 1
    i[0] += 1
    
    # Construct left and right subtree.
    root.left = decodeTreeRecur(i, s, j, arr)
    root.right = decodeTreeRecur(i, s, j, arr)
    
    return root

def decodeTree(s, arr):
    i = [0]
    j = [0]
    return decodeTreeRecur(i, s, j, arr)

def printInorder(root):
    if root is None:
        return
    printInorder(root.left)
    print(root.data, end=" ")
    printInorder(root.right)

if __name__ == "__main__":
    
    s = "1110010010100"
    arr = [10, 20, 40, 50, 30, 70]
    
    root = decodeTree(s, arr)
    printInorder(root)
C#
// C# program to decode a 
// binary tree.
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {

    // Recursive pre-order function to 
    // decode a binary tree.
    static Node decodeTreeRecur(ref int i, string s, 
                                ref int j, List<int> arr) {
        
        // if s[i]==0, return null node
        if (s[i] == '0') {
            i++;
            return null;
        }
        
        // Create a new Node
        Node root = new Node(arr[j++]);
        i++;
        
        // Construct left and right subtree.
        root.left = decodeTreeRecur(ref i, s, ref j, arr);
        root.right = decodeTreeRecur(ref i, s, ref j, arr);
        
        return root;
    }

    static Node decodeTree(string s, List<int> arr) {
        int i = 0, j = 0;
        return decodeTreeRecur(ref i, s, ref j, arr);
    }

    static void printInorder(Node root) {
        if (root == null) return;
        printInorder(root.left);
        Console.Write(root.data + " ");
        printInorder(root.right);
    }

    static void Main(string[] args) {
        
        string s = "1110010010100";
        List<int> arr = new List<int> {10, 20, 40, 50, 30, 70};
        
        Node root = decodeTree(s, arr);
        printInorder(root);
    }
}
JavaScript
// JavaScript program to decode a 
// binary tree.

class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Recursive pre-order function to 
// decode a binary tree.
function decodeTreeRecur(i, s, j, arr) {
    
    // if s[i]==0, return null node
    if (s[i[0]] === '0') {
        i[0]++;
        return null;
    }
    
    // Create a new Node
    const root = new Node(arr[j[0]++]);
    i[0]++;
    
    // Construct left and right subtree.
    root.left = decodeTreeRecur(i, s, j, arr);
    root.right = decodeTreeRecur(i, s, j, arr);
    
    return root;
}

function decodeTree(s, arr) {
    let i = [0];
    let j = [0];
    return decodeTreeRecur(i, s, j, arr);
}

function printInorder(root) {
    if (root === null) return;
    printInorder(root.left);
    console.log(root.data);
    printInorder(root.right);
}

let s = "1110010010100";
let arr = [10, 20, 40, 50, 30, 70];

let root = decodeTree(s, arr);
printInorder(root);

Output
40 20 50 10 30 70 


Next Article
Article Tags :
Practice Tags :

Similar Reads