Trie Data Structure in C++
Last Updated :
28 Jun, 2024
A Trie, also known as a prefix tree, is a tree-like data structure used to store a dynamic set of strings. It is particularly useful for efficient retrieval of keys in a large dataset of strings. In this article, we will explore the Trie data structure, its operations, implementation in C++, and its advantages, disadvantages, and applications.
What is a Trie?
A Trie data structure is a tree-like data structure where each node represents a character of a string sequence. The root node represents an empty string, and each edge represents a character. The path from the root to a node represents a prefix of a string stored in the Trie. This structure allows for efficient insertion, deletion, and search operations.
For example, if we consider a Trie for storing strings with only lowercase characters then each node of the trie will consist of 26 children each representing the presence of letters from a-z. Following are some properties of the trie data structure:
- Each node will represent a single character of the string.
- The root node represents an empty string.
- Each path of the tree represents a word.
- Each node of the trie will have 26 pointers to represent the letters from a-z.
- A boolean flag is used to mark the end of a word in the path of a Trie.
Trie Representation in C++
To represent a node of a Trie in C++, we can declare a class TrieNode in which each node contains an array of pointers to its children and a boolean flag to indicate the end of a word.
class TrieNode {
TrieNode* childrens[26];
bool endofWord;
};
Here,
- childrens[]: is an array of pointers to represent the children of each trie node. To represent letters from a-z the size of the array is declared as 26 where children[0] represents a, children[1] represents b and so on.
- endofWord: is a flag variable that will denote the end of a word in a path of the trie. At any node if the value of endofWord is true it indicates the end of a word in the trie.
The following diagram represents how the words geek, geeks, code, coder and coding will be stored in a Trie:
Example: Trie Data StructureBasic operations on Trie Data Structure
Following are some of the basic operations performed on a Trie data structure:
Operation | Description | Time Complexity | Space Complexity |
---|
Insert | Inserts a new word into the trie. | O(n) | O(n) |
---|
Search | Searches for a word in the trie. | O(n) | O(1) |
---|
Delete | Removes a word from the trie. | O(n) | O(1) |
---|
StartsWith | Checks if there is any word in the trie that starts with the given prefix | O(m) | O(1) |
---|
Here, n represents the length of the word and m represents the length of the prefix.
Insertion Implementation
Following is the algorithm for inserting a word in a trie:
- Initialize a temporary pointer to the root node of the trie.
- For each character in the word:
- Find the index of the character.
- If the character doesn't exists in the current node's children, create a new node for this character.
- Move the pointer to the child node.
- Mark the last node's as the endofWord as true.
Search Implementation
Following is the algorithm for searching a word in a trie:
- Initialize a temporary pointer to the root node of the trie.
- For each character of the word:
- Calculate the index of the character.
- If the corresponding child node doesn't exists return false and return.
- If the child node exists move the pointer to the child node.
- Return true if the endofWord of the last character is true otherwise return false.
Deletion Implementation
Following is the algorithm for deleting a word in a trie:
- Initialize a temporary pointer to the root node of the trie.
- For each character of the word to be deleted:
- Calculate the index of the character.
- If the corresponding child node doesn't; exists return as the word is not present in the trie.
- If the child node exists move the pointer to the child node.
- If the endofWord for the child node is true mark it false and return.
StartsWith Operation Implementation
Following is the algorithm to check if a prefix exits in a trie or not:
- Initialize a temporary pointer to the root node of the trie.
- For each character of the prefix:
- Calculate the index of the character.
- If the corresponding child node doesn't exists return false and return.
- If the child node exists move the pointer to the child node.
- Return true if you have reached at the last character of the prefix.
C++ Program to Implement Trie Data Structure
The following program demonstrates the basic operations on a Trie: insertion, searching, and deletion.
C++
// C++ Program to implement trie
#include <iostream>
#include <string>
using namespace std;
// class for a node of the trie
class TrieNode {
public:
bool endofWord;
TrieNode* children[26];
// Constructore to initialize a trie node
TrieNode()
{
endofWord = false;
for (int i = 0; i < 26; i++) {
children[i] = nullptr;
}
}
};
// class for the Trie implementation
class Trie {
private:
TrieNode* root;
public:
Trie() { root = new TrieNode(); }
// Function to insert a word into the trie
void insert(string word)
{
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (!node->children[index]) {
node->children[index] = new TrieNode();
}
node = node->children[index];
}
node->endofWord = true;
}
// Function to search a word in the trie
bool search(string word)
{
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (!node->children[index]) {
return false;
}
node = node->children[index];
}
return node->endofWord;
}
// Function to check if there is any word in the trie
// that starts with the given prefix
bool startsWith(string prefix)
{
TrieNode* node = root;
for (char c : prefix) {
int index = c - 'a';
if (!node->children[index]) {
return false;
}
node = node->children[index];
}
return true;
}
// Function to delete a word from the trie
void deleteWord(string word)
{
TrieNode* node = root;
for (char c : word) {
int index = c - 'a';
if (!node->children[index]) {
return;
}
node = node->children[index];
}
if (node->endofWord == true) {
node->endofWord = false;
}
}
// Function to print the trie
void print(TrieNode* node, string prefix) const
{
if (node->endofWord) {
cout << prefix << endl;
}
for (int i = 0; i < 26; i++) {
if (node->children[i]) {
print(node->children[i],
prefix + char('a' + i));
}
}
}
// Function to start printing from the root
void print() const { print(root, ""); }
};
int main()
{
// Create a Trie
Trie trie;
// Insert words into the trie
trie.insert("geek");
trie.insert("geeks");
trie.insert("code");
trie.insert("coder");
trie.insert("coding");
// Print the trie
cout << "Trie contents:" << endl;
trie.print();
// Search for words in the trie
cout << "\nSearch results:" << endl;
cout << "geek: " << trie.search("geek") << endl;
cout << "geeks: " << trie.search("geeks") << endl;
cout << "code: " << trie.search("code") << endl;
cout << "coder: " << trie.search("coder") << endl;
cout << "coding: " << trie.search("coding") << endl;
cout << "codex: " << trie.search("codex") << endl;
// Check if prefixes exist in the trie
cout << "\nPrefix results:" << endl;
cout << "ge: " << trie.startsWith("ge") << endl;
cout << "cod: " << trie.startsWith("cod") << endl;
cout << "coz: " << trie.startsWith("coz") << endl;
// Delete words from the trie
trie.deleteWord("coding");
trie.deleteWord("geek");
// Print the trie after deletions
cout << "\nTrie contents after deletions:" << endl;
trie.print();
// Search for words in the trie after deletions
cout << "\nSearch results after deletions:" << endl;
cout << "coding: " << trie.search("coding") << endl;
cout << "geek: " << trie.search("geek") << endl;
return 0;
}
Output
Trie contents:
code
coder
coding
geek
geeks
Search results:
geek: 1
geeks: 1
code: 1
coder: 1
coding: 1
codex: 0
Prefix results:
ge: 1
cod: 1
coz: 0
Trie contents after deletions:
code
coder
geeks
Search results after deletions:
coding: 0
geek: 0
Applications of Trie
Following are some of the common applications of the trie data structure:
- Tries are used to implement the auto complete feature in various search engines.
- Used to implement dictionaries as the allow efficient search for words.
- Used in computer networking to store the routing tables.
- Used by the search engines to index web pages for quick retrieval of pages containing specific keywords.
- Used in phone directory applications to allows users to search for the required contacts efficiently.
Advantages of Trie
- Tries provide efficient search operations with a time complexity of O(m), where m is the length of the key.
- Tries are ideal for prefix-based searches and autocomplete features.
- Tries can be more memory-efficient than hash tables for storing large datasets of strings.
Disadvantages of Trie
- Tries can consume a lot of memory, especially when storing a large number of short strings.
- Implementing a Trie can be more complex compared to other data structures like hash tables.
Related Articles:
You can also go through the following articles to improve your understanding about the trie data structure:
Similar Reads
Trie Data Structure in Java
A Trie Data Structure is nothing but it is a tree-like data structure which is used to efficiently store and retrieve the dynamic set of Strings or Keys. It is certainly used for tasks that will involve searching for strings with common prefix like auto-complete or spell-checking applications. In th
4 min read
What is Data Structure?
A data structure is a way of organizing and storing data in a computer so that it can be accessed and used efficiently. It refers to the logical or mathematical representation of data, as well as the implementation in a computer program. Classification:Data structures can be classified into two broa
2 min read
Structures in C++
C++ Structures are user defined data types which are used to store group of items of different data types. A structure creates a data type that can be used to group items of possibly different types into a single type. SyntaxBefore using structure, we have to first define the structure. The struct k
9 min read
Various Data Structures Used in Compiler
A compiler is a program that converts HLL(High-Level Language) to LLL(Low-Level Language) like machine-level language. The compiler has various data structures that the compiler uses to perform its operations. These data structures are needed by the phases of the compiler. Now we are going to discus
4 min read
Is array a Data Type or Data Structure?
What is Data Type? In computer programming, a data type is a classification of data that determines the type of values that can be stored, manipulated, and processed. It tells the computer what kind of data a particular variable or constant can hold, and what operations can be performed on that data
8 min read
Which data structure is used by Map?
What is a Map? Before learning the data structure used by a map, let us have an overlook of map. Map is the part of the STL library that stores key value pairs in it and no two values have the same keys but the different keys can store similar values. The map stores keys in sorted order. These are s
2 min read
Trie Data Structure using smart pointer and OOP in C++
We will implement trie using smart pointers in C++ and OOP. Here, We have already discussed the implementation of trie data using recursionIn our implementation node of a trie look like : C/C++ Code class TrieNode{ public: // Use of shared_ptr for storing Children // Pointers of TrieNode shared_ptr
6 min read
Data Structures in R Programming
A data structure is a particular way of organizing data in a computer so that it can be used effectively. The idea is to reduce the space and time complexities of different tasks. Data structures in R programming are tools for holding multiple values. Râs base data structures are often organized by
6 min read
Data Structures and Algorithms (DSA) in C++
Data Structures and Algorithms (DSA) are fundamental part of computer science that allow you to store, organize, and process data in ways that maximize performance. This tutorial will guide you through the important data structures and key algorithms using C++ programming language. Why Learn DSA Usi
7 min read
Structures, Unions and Enumerations in C++
Structures, unions and enumerations (enums) are 3 user defined data types in C++. User defined data types allow us to create a data type specifically tailored for a particular purpose. It is generally created from the built-in or derived data types. Let's take a look at each of them one by one. Stru
4 min read