The Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this article, we will explore the insertion and search operations and prefix searches in Trie Data Structure.
Trie data structure consists of nodes connected by edges.
Each node represents a character or a part of a string.
The root node acts as a starting point and does not store any character.
C++
classTrieNode{public:// pointer array for child nodes of each nodeTrieNode*children[26];// Used for indicating ending of stringboolisLeaf;TrieNode(){// initialize the wordEnd variable with false// initialize every index of childNode array with NULLisLeaf=false;for(inti=0;i<26;i++){children[i]=nullptr;}}};
Java
publicclassTrieNode{// Array for child nodes of each nodeTrieNode[]children;// Used for indicating the end of a stringbooleanisEndOfWord;// ConstructorpublicTrieNode(){// Initialize the wordEnd // variable with falseisEndOfWord=false;// Initialize every index of // the child array with null// In Java, we do not have to // explicitely assign null as // the values are by default // assigned as null children=newTrieNode[26];}}
classTrieNode{constructor(){// Initialize the child Node// array with 26 nullsthis.children=Array(26).fill(null);// Initialize wordEnd to the false// indicating that no word ends here yetthis.isEndOfWord=false;}}
Insertion in Trie Data Structure - O(n) Time and O(n) Space
Insert Operation in Trie Data Structure
Inserting "and" in Trie data structure:
Start at the root node: The root node has no character associated with it and its wordEnd value is 0, indicating no complete word ends at this point.
First character "a": Calculate the index using 'a' - 'a' = 0. Check if the child[0] is null. Since it is, create a new TrieNode with the character "a", wordEnd set to 0, and an empty array of pointers. Move to this new node.
Second character "n": Calculate the index using 'n' - 'a' = 13. Check if child[13] is null. It is, so create a new TrieNode with the character "n", wordEnd set to 0, and an empty array of pointers. Move to this new node.
Third character "d": Calculate the index using 'd' - 'a' = 3. Check if child[3] is null. It is, so create a new TrieNode with the character "d", wordEnd set to 1 (indicating the word "and" ends here).
Inserting "ant" in Trie data structure:
Start at the root node: Root node doesn't contain any data but it keep track of every first character of every string that has been inserted.
First character "a": Calculate the index using 'a' - 'a' = 0. Check if the child[0] is null. We already have the "a" node created from the previous insertion. so move to the existing "a" node.
First character "n": Calculate the index using 'n' - 'a' = 13. Check if child[13] is null. It's not, so move to the existing "n" node.
Second character "t": Calculate the index using 't' - 'a' = 19. Check if child[19] is null. It is, so create a new TrieNode with the character "t", wordEnd set to 1 (indicating the word "ant" ends here).
C++
// Method to insert a key into the Trievoidinsert(TrieNode*root,conststring&key){// Initialize the curr pointer with the root nodeTrieNode*curr=root;// Iterate across the length of the stringfor(charc:key){// Check if the node exists for the // current character in the Trieif(curr->children[c-'a']==nullptr){// If node for current character does // not exist then make a new nodeTrieNode*newNode=newTrieNode();// Keep the reference for the newly// created nodecurr->children[c-'a']=newNode;}// Move the curr pointer to the// newly created nodecurr=curr->children[c-'a'];}// Mark the end of the wordcurr->isLeaf=true;}
C
// Function to insert a key into the Trievoidinsert(structTrieNode*root,constchar*key){structTrieNode*curr=root;while(*key){intindex=*key-'a';if(!curr->children[index]){curr->children[index]=getNode();}curr=curr->children[index];key++;}curr->isEndOfWord=true;}
Java
// Method to insert a key into the Triestaticvoidinsert(TrieNoderoot,Stringkey){// Initialize the curr pointer with the root nodeTrieNodecurr=root;// Iterate across the length of the stringfor(charc:key.toCharArray()){// Check if the node exists for the// current character in the Trieif(curr.children[c-'a']==null){// If node for current character does// not exist then make a new nodeTrieNodenewNode=newTrieNode();// Keep the reference for the newly// created nodecurr.children[c-'a']=newNode;}// Move the curr pointer to the// newly created nodecurr=curr.children[c-'a'];}// Mark the end of the wordcurr.isEndOfWord=true;}
Python
# Method to insert a key into the Triedefinsert(root,key):# Initialize the curr pointer with the root nodecurr=root# Iterate across the length of the stringforcinkey:# Check if the node exists for the# current character in the Trieindex=ord(c)-ord('a')ifcurr.children[index]isNone:# If node for current character does# not exist then make a new nodenew_node=TrieNode()# Keep the reference for the newly# created nodecurr.children[index]=new_node# Move the curr pointer to the# newly created nodecurr=curr.children[index]# Mark the end of the wordcurr.isEndOfWord=True
C#
// Method to insert a key into the TriepublicstaticvoidInsert(TrieNoderoot,stringkey){// Initialize the curr pointer with the root nodeTrieNodecurr=root;// Iterate across the length of the stringforeach(charcinkey){// Check if the node exists for the current// character in the Trieif(curr.children[c-'a']==null){// If node for current character does// not exist then make a new nodeTrieNodenewNode=newTrieNode();// Keep the reference for the newly created nodecurr.children[c-'a']=newNode;}// Move the curr pointer to the newly created nodecurr=curr.children[c-'a'];}// Mark the end of the wordcurr.isLeaf=true;}
JavaScript
// Method to insert a key into the Triefunctioninsert(root,key){// Initialize the curr pointer with the root nodeletcurr=root;// Iterate across the length of the stringfor(letcofkey){// Check if the node exists for the // current character in the Trieletindex=c.charCodeAt(0)-'a'.charCodeAt(0);if(curr.children[index]===null){// If node for current character does // not exist then make a new nodeletnewNode=newTrieNode();// Keep the reference for the newly// created nodecurr.children[index]=newNode;}// Move the curr pointer to the// newly created nodecurr=curr.children[index];}// Mark the end of the wordcurr.isEndOfWord=true;}
Time Complexity: O(n), where n is the length of the word to insert. Auxiliary Space: O(n)
Searching in Trie Data Structure - O(n) Time and O(1) Space
Searching for a key in Trie data structure is similar to its insert operation. However, It only compares the characters and moves down. The search can terminate due to the end of a string or lack of key in the trie.
Here's a visual representation of searching word "dad" in Trie data structure: Let's assume that we have successfully inserted the words "and", "ant", and "dad" into our Trie, and we have to search for specific words within the Trie data structure. Let's try searching for the word "dad":
Search Operation in Trie Data Structure
Here's a visual representation of searching word "dad" in Trie data structure: Let's assume that we have successfully inserted the words "and", "ant", and "dad" into our Trie, and we have to search for specific words within the Trie data structure. Let's try searching for the word "dad":
We start at the root node.
We follow the branch corresponding to the character 'd'.
We follow the branch corresponding to the character 'a'.
We follow the branch corresponding to the character 'd'.
We reach the end of the word and wordEnd flag is 1.
This means that "dad" is present in the Trie.
C++
// Method to search a key in the Trieboolsearch(TrieNode*root,conststring&key){// Initialize the curr pointer with the root nodeTrieNode*curr=root;// Iterate across the length of the stringfor(charc:key){// Check if the node exists for the // current character in the Trieif(curr->children[c-'a']==nullptr)returnfalse;// Move the curr pointer to the // already existing node for the // current charactercurr=curr->children[c-'a'];}// Return true if the word exists // and is marked as endingreturncurr->isLeaf;}
C
// Function to search a key in the Trieboolsearch(structTrieNode*root,constchar*key){structTrieNode*curr=root;while(*key){intindex=*key-'a';if(!curr->children[index]){returnfalse;}curr=curr->children[index];key++;}return(curr!=NULL&&curr->isEndOfWord);}
Java
// Method to search a key in the Triestaticbooleansearch(TrieNoderoot,Stringkey){// Initialize the curr pointer with the root nodeTrieNodecurr=root;// Iterate across the length of the stringfor(charc:key.toCharArray()){// Check if the node exists for the// current character in the Trieif(curr.children[c-'a']==null)returnfalse;// Move the curr pointer to the// already existing node for the// current charactercurr=curr.children[c-'a'];}// Return true if the word exists// and is marked as endingreturncurr.isEndOfWord;}
Python
# Method to search a key in the Triedefsearch(root,key):# Initialize the curr pointer with the root nodecurr=root# Iterate across the length of the stringforcinkey:# Check if the node exists for the # current character in the Trieindex=ord(c)-ord('a')ifcurr.children[index]isNone:returnFalse# Move the curr pointer to the # already existing node for the # current charactercurr=curr.children[index]# Return true if the word exists # and is marked as endingreturncurr.isEndOfWord
C#
// Method to search a key in the TriepublicstaticboolSearch(TrieNoderoot,stringkey){// Initialize the curr pointer with the root nodeTrieNodecurr=root;// Iterate across the length of the stringforeach(charcinkey){// Check if the node exists for the current// character in the Trieif(curr.children[c-'a']==null)returnfalse;// Move the curr pointer to the already// existing node for the current charactercurr=curr.children[c-'a'];}// Return true if the word exists and// is marked as endingreturncurr.isLeaf;}
JavaScript
// Method to search a key in the Triefunctionsearch(root,key){// Initialize the curr pointer with the root nodeletcurr=root;// Iterate across the length of the stringfor(letcofkey){// Check if the node exists for the // current character in the Trieletindex=c.charCodeAt(0)-'a'.charCodeAt(0);if(curr.children[index]===null)returnfalse;// Move the curr pointer to the // already existing node for the // current charactercurr=curr.children[index];}// Return true if the word exists // and is marked as endingreturncurr.isEndOfWord;}
Time Complexity: O(n), where n is the length of the word to search. Auxiliary Space: O(1)
Prefix Searching in Trie Data Structure - O(n) Time and O(1) Space
Searching for a prefix in a Trie data structure is similar to searching for a key, but the search does not need to reach the end of the word. Instead, we stop as soon as we reach the end of the prefix or if any character in the prefix doesn't exist in the Trie.
Here's a visual representation of prefix searching for the word 'da' in the Trie data structure: Let's assume that we have successfully inserted the words 'and', 'ant', and 'dad' into our Trie. Now, let's search for the prefix 'da' within the Trie data structure.
We start at the root node.
We follow the branch corresponding to the character 'd'.
We move to the node corresponding to the character 'a'.
We reach the end of the prefix "da". Since we haven't encountered any missing characters along the way, we return true.
C++
// Method to Seach Prefix key in TrieboolisPrefix(TrieNode*root,string&key){TrieNode*current=root;for(charc:key){intindex=c-'a';// If character doesn't exist, return falseif(current->children[index]==nullptr){returnfalse;}current=current->children[index];}returntrue;}
Java
booleanisPrefix(TrieNoderoot,Stringkey){TrieNodecurrent=root;for(charc:key.toCharArray()){intindex=c-'a';// If character doesn't exist, return falseif(current.children[index]==null){returnfalse;}current=current.children[index];}returntrue;}
Python
defis_prefix(root,key):current=rootforcinkey:index=ord(c)-ord('a')# If character doesn't exist, return falseifcurrent.children[index]isNone:returnFalsecurrent=current.children[index]returnTrue
C#
boolIsPrefix(TrieNoderoot,stringkey){TrieNodecurrent=root;foreach(charcinkey){intindex=c-'a';// If character doesn't exist, return falseif(current.Children[index]==null){returnfalse;}current=current.Children[index];}returntrue;}
JavaScript
functionisPrefix(root,key){letcurrent=root;for(letcofkey){letindex=c.charCodeAt(0)-"a".charCodeAt(0);// If character doesn't exist, return falseif(current.children[index]===null){returnfalse;}current=current.children[index];}returntrue;}
Time Complexity: O(n), where n is the length of the word to search. Auxiliary Space: O(1)
Implementation of Insert, Search and Prefix Searching Operations in Trie Data Structure
Now that we've learned how to insert words into a Trie, search for complete words, and perform prefix searches, let's do some hands-on practice.
We'll start by inserting the following words into the Trie: ["and", "ant", "do", "dad"]. Then, we'll search for the presence of these words: ["do", "gee", "bat"]. Finally, we'll check for the following prefixes: ["ge", "ba", "do", "de"].
Steps-by-step approach:
Create a root node with the help of TrieNode() constructor.
Store a collection of strings that have to be inserted in the Trie in a vector of strings say, arr.
Inserting all strings in Trie with the help of the insertKey() function,
Search strings with the help of searchKey() function.
Prefix searching with the help of isPrefix() function.
C++
#include<bits/stdc++.h>usingnamespacestd;classTrieNode{public:// Array for children nodes of each nodeTrieNode*children[26];// for end of wordboolisLeaf;TrieNode(){isLeaf=false;for(inti=0;i<26;i++){children[i]=nullptr;}}};// Method to insert a key into the Trievoidinsert(TrieNode*root,conststring&key){// Initialize the curr pointer with the root nodeTrieNode*curr=root;// Iterate across the length of the stringfor(charc:key){// Check if the node exists for the// current character in the Trieif(curr->children[c-'a']==nullptr){// If node for current character does// not exist then make a new nodeTrieNode*newNode=newTrieNode();// Keep the reference for the newly// created nodecurr->children[c-'a']=newNode;}// Move the curr pointer to the// newly created nodecurr=curr->children[c-'a'];}// Mark the end of the wordcurr->isLeaf=true;}// Method to search a key in the Trieboolsearch(TrieNode*root,conststring&key){if(root==nullptr){returnfalse;}// Initialize the curr pointer with the root nodeTrieNode*curr=root;// Iterate across the length of the stringfor(charc:key){// Check if the node exists for the// current character in the Trieif(curr->children[c-'a']==nullptr)returnfalse;// Move the curr pointer to the// already existing node for the// current charactercurr=curr->children[c-'a'];}// Return true if the word exists// and is marked as endingreturncurr->isLeaf;}// Method to check if a prefix exists in the TrieboolisPrefix(TrieNode*root,conststring&prefix){// Initialize the curr pointer with the root nodeTrieNode*curr=root;// Iterate across the length of the prefix stringfor(charc:prefix){// Check if the node exists for the current character in the Trieif(curr->children[c-'a']==nullptr)returnfalse;// Move the curr pointer to the already existing node// for the current charactercurr=curr->children[c-'a'];}// If we reach here, the prefix exists in the Triereturntrue;}intmain(){// Create am example TrieTrieNode*root=newTrieNode();vector<string>arr={"and","ant","do","dad"};for(conststring&s:arr){insert(root,s);}// One by one search stringsvector<string>searchKeys={"do","gee","bat"};for(string&s:searchKeys){if(search(root,s))cout<<"true ";elsecout<<"false ";}cout<<"\n";// One by one search for prefixesvector<string>prefixKeys={"ge","ba","do","de"};for(string&s:prefixKeys){if(isPrefix(root,s))cout<<"true ";elsecout<<"false ";}return0;}
Java
classTrieNode{TrieNode[]children;booleanisLeaf;TrieNode(){children=newTrieNode[26];isLeaf=false;}}publicclassTrie{TrieNoderoot;publicTrie(){root=newTrieNode();}// Method to insert a key into the Triepublicvoidinsert(Stringkey){TrieNodecurr=root;for(charc:key.toCharArray()){if(curr.children[c-'a']==null){curr.children[c-'a']=newTrieNode();}curr=curr.children[c-'a'];}curr.isLeaf=true;}// Method to search a key in the Triepublicbooleansearch(Stringkey){TrieNodecurr=root;for(charc:key.toCharArray()){if(curr.children[c-'a']==null){returnfalse;}curr=curr.children[c-'a'];}returncurr.isLeaf;}// Method to check if a prefix exists in the TriepublicbooleanisPrefix(Stringprefix){TrieNodecurr=root;for(charc:prefix.toCharArray()){if(curr.children[c-'a']==null){returnfalse;}curr=curr.children[c-'a'];}returntrue;}publicstaticvoidmain(String[]args){Trietrie=newTrie();String[]arr={"and","ant","do","dad"};for(Strings:arr){trie.insert(s);}String[]searchKeys={"do","gee","bat"};for(Strings:searchKeys){if(trie.search(s))System.out.print("true ");elseSystem.out.print("false ");}System.out.println();String[]prefixKeys={"ge","ba","do","de"};for(Strings:prefixKeys){if(trie.isPrefix(s))System.out.print("true ");elseSystem.out.print("false ");}}}
Python
classTrieNode:def__init__(self):self.children=[None]*26self.isLeaf=FalseclassTrie:def__init__(self):self.root=TrieNode()# Method to insert a key into the Triedefinsert(self,key):curr=self.rootforcinkey:index=ord(c)-ord('a')ifcurr.children[index]isNone:curr.children[index]=TrieNode()curr=curr.children[index]curr.isLeaf=True# Method to search a key in the Triedefsearch(self,key):curr=self.rootforcinkey:index=ord(c)-ord('a')ifcurr.children[index]isNone:returnFalsecurr=curr.children[index]returncurr.isLeaf# Method to check if a prefix exists in the TriedefisPrefix(self,prefix):curr=self.rootforcinprefix:index=ord(c)-ord('a')ifcurr.children[index]isNone:returnFalsecurr=curr.children[index]returnTrueif__name__=='__main__':trie=Trie()arr=["and","ant","do","dad"]forsinarr:trie.insert(s)searchKeys=["do","gee","bat"]forsinsearchKeys:iftrie.search(s):print("true",end=" ")else:print("false",end=" ")print()prefixKeys=["ge","ba","do","de"]forsinprefixKeys:iftrie.isPrefix(s):print("true",end=" ")else:print("false",end=" ")
C#
// Using System.Collections.Generic;usingSystem;classTrieNode{publicTrieNode[]children=newTrieNode[26];publicboolisLeaf;publicTrieNode(){isLeaf=false;for(inti=0;i<26;i++){children[i]=null;}}}classTrie{privateTrieNoderoot;publicTrie(){root=newTrieNode();}// Method to insert a key into the TriepublicvoidInsert(stringkey){TrieNodecurr=root;foreach(charcinkey){if(curr.children[c-'a']==null){curr.children[c-'a']=newTrieNode();}curr=curr.children[c-'a'];}curr.isLeaf=true;}// Method to search a key in the TriepublicboolSearch(stringkey){TrieNodecurr=root;foreach(charcinkey){if(curr.children[c-'a']==null)returnfalse;curr=curr.children[c-'a'];}returncurr.isLeaf;}// Method to check if a prefix exists in the TriepublicboolisPrefix(stringprefix){TrieNodecurr=root;foreach(charcinprefix){if(curr.children[c-'a']==null)returnfalse;curr=curr.children[c-'a'];}returntrue;}}classGfG{staticvoidMain(){Trietrie=newTrie();string[]arr={"and","ant","do","dad"};foreach(stringsinarr){trie.Insert(s);}// One by one search stringsstring[]searchKeys={"do","gee","bat"};foreach(stringsinsearchKeys){if(trie.Search(s))Console.Write("true ");elseConsole.Write("false ");}Console.WriteLine();// One by one search for prefixesstring[]prefixKeys={"ge","ba","do","de"};foreach(stringsinprefixKeys){if(trie.isPrefix(s))Console.Write("true ");elseConsole.Write("false ");}}}
JavaScript
// TrieNode classclassTrieNode{constructor(){this.children=newArray(26).fill(null);this.isLeaf=false;}}// Trie classclassTrie{constructor(){this.root=newTrieNode();}// Method to insert a key into the Trieinsert(key){letcurr=this.root;for(letcofkey){if(curr.children[c.charCodeAt(0)-"a".charCodeAt(0)]===null){curr.children[c.charCodeAt(0)-"a".charCodeAt(0)]=newTrieNode();}curr=curr.children[c.charCodeAt(0)-"a".charCodeAt(0)];}curr.isLeaf=true;}// Method to search a key in the Triesearch(key){letcurr=this.root;for(letcofkey){if(curr.children[c.charCodeAt(0)-"a".charCodeAt(0)]===null)returnfalse;curr=curr.children[c.charCodeAt(0)-"a".charCodeAt(0)];}returncurr.isLeaf;}// Method to check if a prefix exists in the TrieisPrefix(prefix){letcurr=this.root;for(letcofprefix){if(curr.children[c.charCodeAt(0)-"a".charCodeAt(0)]===null)returnfalse;curr=curr.children[c.charCodeAt(0)-"a".charCodeAt(0)];}returntrue;}}consttrie=newTrie();constarr=["and","ant","do","dad"];for(letsofarr){trie.insert(s);}// One by one search stringsconstsearchKeys=["do","gee","bat"];console.log(searchKeys.map(s=>trie.search(s)?"true":"false").join(" "));// One by one search for prefixesconstprefixKeys=["ge","ba","do","de"];console.log(prefixKeys.map(s=>trie.isPrefix(s)?"true":"false").join(" "));
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.