Trie is an efficient information retrieval data structure. In our previous post on trie we have discussed about basics of trie and how to insert and search a key in trie. In this post we will discuss about displaying all of the content of a trie. That is, to display all of the keys present in the Trie.
Examples:
Input: If Trie is root
/ \ \
t a b
| | |
h n y
| | \ |
e s y e
/ | |
i r w
| | |
r e e
|
r
Output: Contents of Trie:
answer
any
bye
their
there
The idea to do this is to start traversing from the root node of trie, whenever we find a NON-NULL child node, we add parent key of child node in the "string str" at the current index(level) and then recursively call the same process for the child node and same goes on till we find the node which is a leafnode, which actually marks the end of the string.
Below is the C++ implementation of the above idea:
CPP
// CPP program to display content of Trie
#include <iostream>
#include <string.h>
#define alpha_size 26
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
using namespace std;
// Trie node
struct TrieNode
{
struct TrieNode* children[alpha_size];
bool isLeaf;
};
// Returns new trie node (initialized to NULLs)
struct TrieNode* createNode()
{
struct TrieNode* pNode = new TrieNode;
for (int i = 0; i < alpha_size; i++)
pNode->children[i] = NULL;
pNode->isLeaf = false;
return pNode;
};
// function to insert a node in Trie
void insert_node(struct TrieNode* root, char* key)
{
int level;
int length = strlen(key);
struct TrieNode* pCrawl = root;
for (level = 0; level < length; level++)
{
int index = key[level] - 'a';
if (pCrawl->children[index] == NULL)
pCrawl->children[index] = createNode();
pCrawl = pCrawl->children[index];
}
pCrawl->isLeaf = true;
}
// function to check if current node is leaf node or not
bool isLeafNode(struct TrieNode* root)
{
return root->isLeaf != false;
}
// function to display the content of Trie
void display(struct TrieNode* root, char str[], int level)
{
// If node is leaf node, it indicates end
// of string, so a null character is added
// and string is displayed
if (isLeafNode(root))
{
str[level] = '\0';
cout << str << endl;
}
int i;
for (i = 0; i < alpha_size; i++)
{
// if NON NULL child is found
// add parent key to str and
// call the display function recursively
// for child node
if (root->children[i])
{
str[level] = i + 'a';
display(root->children[i], str, level + 1);
}
}
}
// Driver program to test above functions
int main()
{
// Keys to be inserted in Trie
char keys[][8] = { "the", "a", "there", "answer",
"any", "by", "bye", "their" };
struct TrieNode* root = createNode();
// Inserting keys in Trie
for (int j = 0; j < ARRAY_SIZE(keys); j++)
insert_node(root, keys[j]);
int level = 0;
char str[20];
// Displaying content of Trie
cout << "Content of Trie: " << endl;
display(root, str, level);
}
Java
// Java program to display content of Trie
import java.util.*;
// Trie node
class TrieNode {
TrieNode[] children = new TrieNode[26];
boolean isLeaf;
// Returns new trie node (initialized to NULLs)
public TrieNode() {
for (int i = 0; i < 26; i++) {
children[i] = null;
}
isLeaf = false;
}
}
class Trie {
TrieNode root;
// function to insert a node in Trie
void insert(String key) {
int level;
int length = key.length();
TrieNode pCrawl = root;
for (level = 0; level < length; level++) {
int index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null) {
pCrawl.children[index] = new TrieNode();
}
pCrawl = pCrawl.children[index];
}
pCrawl.isLeaf = true;
}
// function to check if current node is leaf node or not
boolean isLeafNode(TrieNode root) {
return root.isLeaf != false;
}
// function to display the content of Trie
void display(TrieNode root, char[] str, int level) {
// If node is leaf node, it indicates end
// of string, so a null character is added
// and string is displayed
if (isLeafNode(root)) {
for (int k = level; k < str.length; k++)
str[k] = 0;
System.out.println(str);
}
int i;
for (i = 0; i < 26; i++) {
// if NON NULL child is found
// add parent key to str and
// call the display function recursively
// for child node
if (root.children[i] != null) {
str[level] = (char) (i + 'a');
display(root.children[i], str, level + 1);
}
}
}
}
public class Main {
// Driver program to test above functions
public static void main(String[] args) {
// Keys to be inserted in Trie
String[] keys = { "the", "a", "there", "answer",
"any", "by", "bye", "their" };
Trie trie = new Trie();
trie.root = new TrieNode();
// Inserting keys in Trie
int n = keys.length;
for (int j = 0; j < n; j++) {
trie.insert(keys[j]);
}
int level = 0;
char[] str = new char[20];
// Displaying content of Trie
System.out.println("Content of Trie: ");
trie.display(trie.root, str, level);
}
}
// This code is contributed by Aman Kumar.
Python3
##Display words in a trie (recursive approach)
class TrieNode:
def __init__(self):
self.children=[None]*26
self.isEndOfWord=False
class Trie:
def __init__(self):
self.root=self.getNode()
def getNode(self):
return TrieNode()
def _charToIndex(self,ch):
return ord(ch)-ord('a')
def search(self,key):
pCrawl=self.root
length=len(key)
for level in range(length):
index=self._charToIndex(key[level])
if not pCrawl.children[index]:
return False
pCrawl=pCrawl.children[index]
return pCrawl.isEndOfWord
def insert(self,key):
pCrawl=self.root
length=len(key)
for level in range(length):
index=self._charToIndex(key[level])
if not pCrawl.children[index]:
pCrawl.children[index]=self.getNode()
pCrawl=pCrawl.children[index]
pCrawl.isEndOfWord=True
def delete(self,key):
queue=[]
pCrawl=self.root
prev=self.root
length=len(key)
for level in range(length):
index=self._charToIndex(key[level])
if not pCrawl.children[index]:
return
if pCrawl.isEndOfWord:
queue.append([pCrawl,level])
pCrawl=pCrawl.children[index]
if pCrawl.isEndOfWord == False:
return
##If is a prefix of another tree, just change leaf
flag=False
for i in range(26):
if pCrawl.children[index]:
flag=True
if flag:
pCrawl.isEndOfWord==False
return
##If not a prefix but a tree longer than others, delete until isEndOfWord == True again/reach root(a unique trie)
if len(queue)==0:
index=self._charToIndex(key[0])
self.root.children[index]=None
return
pCrawl,level=queue.pop()
index=self._charToIndex(key[level])
pCrawl.children[index]=None
def haschild(self,node):
for i in range(26):
if node.children[i]:
return True
return False
def displayUtil(self,visited,node,str):
index=0
while index<26:
if node.children[index]:
str+=chr(97+index)
#print(2,str)
if node.children[index].isEndOfWord == False:
self.displayUtil(visited,node.children[index],str)
str=str[0 : (len(str)-1)]
else:
if str not in visited:
visited.append(str)
if self.haschild(node.children[index]):
self.displayUtil(visited,node.children[index],str)
str=str[0 : (len(str)-1)]
index+=1
def display(self):
visited=[]
str=''
self.displayUtil(visited,self.root,str)
print("Content of Trie:")
for i in range(len(visited)):
print(visited[i])
keys = ["the","a","there","bye","any",
"by","their","answer"]
output = ["Not present in trie","Present in trie"]
t=Trie()
for key in keys:
t.insert(key)
t.display()
#This code is contributed by Zhaoxin Ban
C#
// C# program to display content of Trie
using System;
// Trie node
public class TrieNode
{
public TrieNode[] children = new TrieNode[26];
public bool isLeaf;
// Returns new trie node (initialized to NULLs)
public TrieNode()
{
for (int i = 0; i < 26; i++)
{
children[i] = null;
}
isLeaf = false;
}
}
public class Trie
{
public TrieNode root;
// function to insert a node in Trie
public void Insert(string key)
{
int level;
int length = key.Length;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
int index = key[level] - 'a';
if (pCrawl.children[index] == null)
{
pCrawl.children[index] = new TrieNode();
}
pCrawl = pCrawl.children[index];
}
pCrawl.isLeaf = true;
}
// function to check if current node is leaf node or not
public bool IsLeafNode(TrieNode root)
{
return root.isLeaf != false;
}
// function to display the content of Trie
public void Display(TrieNode root, char[] str, int level)
{
// If node is leaf node, it indicates end
// of string, so a null character is added
// and string is displayed
if (IsLeafNode(root))
{
for (int k = level; k < str.Length; k++)
{
str[k] = '\0';
}
Console.WriteLine(str);
}
int i;
for (i = 0; i < 26; i++)
{
// if NON NULL child is found
// add parent key to str and
// call the display function recursively
// for child node
if (root.children[i] != null)
{
str[level] = (char) (i + 'a');
Display(root.children[i], str, level + 1);
}
}
}
}
public class Program
{
// Driver program to test above functions
public static void Main()
{
// Keys to be inserted in Trie
string[] keys = { "the", "a", "there", "answer", "any", "by", "bye", "their" };
Trie trie = new Trie();
trie.root = new TrieNode();
// Inserting keys in Trie
int n = keys.Length;
for (int j = 0; j < n; j++)
{
trie.Insert(keys[j]);
}
int level = 0;
char[] str = new char[20];
// Displaying content of Trie
Console.WriteLine("Content of Trie: ");
trie.Display(trie.root, str, level);
}
}
// This code is contributed by Utkarsh Kumar.
JavaScript
// Trie node
class TrieNode {
constructor() {
this.children = new Array(26);
this.isLeaf = false;
// Initialize all children to null
for (let i = 0; i < 26; i++) {
this.children[i] = null;
}
}
}
class Trie {
constructor() {
this.root = new TrieNode();
}
// function to insert a node in Trie
insert(key) {
let level;
const length = key.length;
let pCrawl = this.root;
for (level = 0; level < length; level++) {
const index = key[level].charCodeAt(0) - 'a'.charCodeAt(0);
if (!pCrawl.children[index]) {
pCrawl.children[index] = new TrieNode();
}
pCrawl = pCrawl.children[index];
}
pCrawl.isLeaf = true;
}
// function to check if current node is leaf node or not
isLeafNode(root) {
return root.isLeaf !== false;
}
// function to display the content of Trie
display(root, str, level) {
// If node is leaf node, it indicates end
// of string, so a null character is added
// and string is displayed
if (this.isLeafNode(root)) {
for (let k = level; k < str.length; k++) {
str[k] = '';
}
console.log(str.join(""));
}
for (let i = 0; i < 26; i++) {
// if NON NULL child is found
// add parent key to str and
// call the display function recursively
// for child node
if (root.children[i] !== null) {
str[level] = String.fromCharCode(i + 'a'.charCodeAt(0));
this.display(root.children[i], str, level + 1);
}
}
}
}
// Driver program to test above functions
const keys = ["the", "a", "there", "answer", "any", "by", "bye", "their"];
const trie = new Trie();
// Inserting keys in Trie
const n = keys.length;
for (let j = 0; j < n; j++) {
trie.insert(keys[j]);
}
const level = 0;
const str = new Array(20).fill(0);
// Displaying content of Trie
console.log("Content of Trie: ");
trie.display(trie.root, str, level);
OutputContent of Trie:
a
answer
any
by
bye
the
their
there
Time Complexity: O(N*M) where N is the number of keys to be inserted in the Trie and M is the maximum length of a key.
Auxiliary Space: O(N*M)
NOTE: The above algorithm displays the content of Trie in Lexicographically Sorted order.
Some useful applications of Trie are: