Trie is an efficient information retrieval data structure. Using Trie, search complexities can be brought to an optimal limit (key length).
Given a trie. The task is to print the characters in a bottom-up manner
Bottom-up traversal:
First print string of left most subtree(from bottom to top) then print string of second left subtree(from bottom to top) then print for third left subtree and so on.
It is similar to post-order traversal of a tree
Example:
Input :
root
/ \
a t
| |
n h
| \ |
s y e
| | \
w i r
| | |
e r e
|
r
Output : r, e, w, s, y, n, a, r, i, e, r, e, h, t
Input :
root
/ \
c t
| |
a h
| \ |
l t e
| | \
l i r
| \ | |
e i r e
| |
r n
|
g
Output : r, e, g, n, i, l, l, t, a, c, r, i, e, r, e, h, t
Explanation :
In the first example, the root has two parts. First part contains strings: “answer” and “any”.
the second part with strings “their” and “there”.
- Now first we got to left subtree containing strings “answer” and “any” which separates by character ‘n’. Now ‘n’ separates two-part of characters ‘s’, ‘w’, ‘e’, ‘r’ and ‘y’. so print ‘s’, ‘w’, ‘e’, ‘r’ in reverse order then print ‘y’ and go up and print ‘n'(which separates string) then go up and print ‘a’. Now first left subtree has printed in bottom up manner ‘r’, ‘e’, ‘w’, ‘s’, ‘y’, ‘n’, ‘a’.
- Do the same thing for another subtree of the root which contains strings “their” and “there” which is separated by character ‘e’.
Approach :
The idea to do this is to start traversing from the root node of the trie, whenever we find a NON-NULL child node, we recursively move ahead when we get “NULL” we return simply and print the value of current node and same goes un till we find the node which is a leaf node, which actually marks the end of the string.
Below is the implementation of the above approach :
C++
#include <bits/stdc++.h>
using namespace std;
#define CHILDREN 26
#define MAX 100
struct trie {
trie* child[CHILDREN];
bool endOfWord;
};
trie* createNode()
{
trie* temp = new trie();
temp->endOfWord = false ;
for ( int i = 0; i < CHILDREN; i++) {
temp->child[i] = NULL;
}
return temp;
}
void insertRecursively(trie* itr, string str, int i)
{
if (i < str.length()) {
int index = str[i] - 'a' ;
if (itr->child[index] == NULL) {
itr->child[index] = createNode();
}
insertRecursively(itr->child[index], str, i + 1);
}
else {
itr->endOfWord = true ;
}
}
void insert(trie* itr, string str)
{
insertRecursively(itr, str, 0);
}
void printPattern(trie* itr)
{
if (itr == NULL)
return ;
for ( int i = 0; i < CHILDREN; i++) {
printPattern(itr->child[i]);
if (itr->child[i] != NULL) {
char ch = (i + 97);
cout << ch << ", " ;
}
}
}
int main()
{
trie* root = createNode();
insert(root, "their" );
insert(root, "there" );
insert(root, "answer" );
insert(root, "any" );
printPattern(root);
return 0;
}
|
Java
public class Main
{
static int CHILDREN = 26 ;
static class trie {
public boolean endOfWord;
public trie[] child;
public trie()
{
endOfWord = false ;
child = new trie[CHILDREN];
}
}
static trie createNode()
{
trie temp = new trie();
temp.endOfWord = false ;
for ( int i = 0 ; i < CHILDREN; i++)
{
temp.child[i] = null ;
}
return temp;
}
static void insertRecursively(trie itr, String str, int i)
{
if (i < str.length()) {
int index = str.charAt(i) - 'a' ;
if (itr.child[index] == null )
{
itr.child[index] = createNode();
}
insertRecursively(itr.child[index], str, i + 1 );
}
else
{
itr.endOfWord = true ;
}
}
static void insert(trie itr, String str)
{
insertRecursively(itr, str, 0 );
}
static void printPattern(trie itr)
{
if (itr == null )
return ;
for ( int i = 0 ; i < CHILDREN; i++) {
printPattern(itr.child[i]);
if (itr.child[i] != null ) {
char ch = ( char )(i + 97 );
System.out.print(ch + ", " );
}
}
}
public static void main(String[] args) {
trie root = createNode();
insert(root, "their" );
insert(root, "there" );
insert(root, "answer" );
insert(root, "any" );
printPattern(root);
}
}
|
Python3
CHILDREN = 26
MAX = 100
class trie:
def __init__( self ):
self .child = [ None for i in range (CHILDREN)]
self .endOfWord = False
def createNode():
temp = trie()
return temp
def insertRecursively(itr, str , i):
if (i < len ( str )):
index = ord ( str [i]) - ord ( 'a' )
if (itr.child[index] = = None ):
itr.child[index] = createNode()
insertRecursively(itr.child[index], str , i + 1 )
else :
itr.endOfWord = True
def insert(itr, str ):
insertRecursively(itr, str , 0 )
def printPattern(itr):
if (itr = = None ):
return
for i in range (CHILDREN):
printPattern(itr.child[i])
if (itr.child[i] ! = None ):
ch = chr (i + 97 )
print (ch,end = ', ' )
if __name__ = = '__main__' :
root = createNode()
insert(root, "their" )
insert(root, "there" )
insert(root, "answer" )
insert(root, "any" )
printPattern(root)
|
C#
using System;
class GFG {
static int CHILDREN = 26;
class trie {
public bool endOfWord;
public trie[] child;
public trie()
{
endOfWord = false ;
child = new trie[CHILDREN];
}
}
static trie createNode()
{
trie temp = new trie();
temp.endOfWord = false ;
for ( int i = 0; i < CHILDREN; i++)
{
temp.child[i] = null ;
}
return temp;
}
static void insertRecursively(trie itr, string str, int i)
{
if (i < str.Length) {
int index = str[i] - 'a' ;
if (itr.child[index] == null )
{
itr.child[index] = createNode();
}
insertRecursively(itr.child[index], str, i + 1);
}
else
{
itr.endOfWord = true ;
}
}
static void insert(trie itr, string str)
{
insertRecursively(itr, str, 0);
}
static void printPattern(trie itr)
{
if (itr == null )
return ;
for ( int i = 0; i < CHILDREN; i++) {
printPattern(itr.child[i]);
if (itr.child[i] != null ) {
char ch = ( char )(i + 97);
Console.Write(ch + ", " );
}
}
}
static void Main() {
trie root = createNode();
insert(root, "their" );
insert(root, "there" );
insert(root, "answer" );
insert(root, "any" );
printPattern(root);
}
}
|
Javascript
<script>
let CHILDREN = 26;
class trie
{
constructor()
{
this .child = new Array(CHILDREN);
this .endOfWord = false ;
}
}
function createNode()
{
let temp = new trie();
temp.endOfWord = false ;
for (let i = 0; i < CHILDREN; i++)
{
temp.child[i] = null ;
}
return temp;
}
function insertRecursively(itr, str, i)
{
if (i < str.length) {
let index = str[i].charCodeAt() - 'a' .charCodeAt();
if (itr.child[index] == null )
{
itr.child[index] = createNode();
}
insertRecursively(itr.child[index], str, i + 1);
}
else
{
itr.endOfWord = true ;
}
}
function insert(itr, str)
{
insertRecursively(itr, str, 0);
}
function printPattern(itr)
{
if (itr == null )
return ;
for (let i = 0; i < CHILDREN; i++) {
printPattern(itr.child[i]);
if (itr.child[i] != null ) {
let ch = String.fromCharCode(i + 97);
document.write(ch + ", " );
}
}
}
let root = createNode();
insert(root, "their" );
insert(root, "there" );
insert(root, "answer" );
insert(root, "any" );
printPattern(root);
</script>
|
Outputr, e, w, s, y, n, a, r, i, e, r, e, h, t,
Time Complexity: O(n), where ‘n’ is the Total length of the given words(approx). Since Program will go through each and every node in the trie to print
Auxiliary Space: O(n*CHILDREN), where ‘n’ represents the number of alphabets in the trie and CHILDREN is the number of children per node(which is 26 in this case). Since Program will go to each and every node in trie to print.