Succinct Encoding of Binary Tree
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).
Please Login to comment...