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 broad
2 min read
Structures in C++
C++ Structures are used to create user defined data types which are used to store group of items of different data types.SyntaxBefore using structure, we have to first define the structure using the struct keyword as shown:C++struct name{ type1 mem1; type2 mem2; ... };where structure name is name an
8 min read
C++ - Pointer to Structure
Pointer to structure in C++ can also be referred to as Structure Pointer. A structure Pointer in C++ is defined as the pointer which points to the address of the memory block that stores a structure. Below is an example of the same: Syntax: struct name_of_structure *ptr; // Initialization of structu
2 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
Types of Heap Data Structure
Different types of heap data structures include fundamental types like min heap and max heap, binary heap and many more. In this post, we will look into their characteristics, and their use cases. Understanding the characteristics and use cases of these heap data structures helps in choosing the mos
8 min read
Vector data() in C++ STL
In C++, the vector data() is a built-in function used to access the internal array used by the vector to store its elements. In this article, we will learn about vector data() in C++.Letâs take a look at an example that illustrates the vector data() method:C++#include <bits/stdc++.h> using nam
2 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
Policy based data structures in g++
The g++ compiler also supports some data structures that are not part of the C++ standard library. Such structures are called policy-based data structures. These data structures are designed for high-performance, flexibility, semantic safety, and conformance to the corresponding containers in std.To
6 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.Struc
3 min read