This article is about Trie and Trees data structure.
trie
In computer science , a trie , also called digital tree and sometimes radix tree or prefix tree (as they can be searched by prefixes), is an ordered tree data structure that is used to store a dynamic set or associative array where the keys are usually strings . Unlike a binary search tree , no node in the tree stores the key associated with that node; instead, its position in the tree defines the key with which it is associated. All the descendants of a node have a common prefix of the string associated with that node, and the root is associated with the empty string . Values are normally not associated with every node, only with leaves and some inner nodes that correspond to keys of interest. For the space-optimized presentation of prefix tree, see compact prefix tree .
Read more
Trie is one of the most important data structure for autocomplete.
Trie Problems
Various problems on Trie can be found here
Trie explanation
Trie code implementation is based on this article.
Trie Code
1
2 typedef int trieValueT;
3
4 typedef struct trieNodeTag {
5 char key;
6 int words;
7 int prefix;
8 trieValueT value;
9 struct trieNodeTag *next, *children;
10 } trieNodeT;
11
12 typedef struct trieCDT {
13 trieNodeT *root;
14 } trieCDT;
15
16 typedef struct trieCDT *trieADT;
17
18 // Functions
19 void trieCreate(trieCDT *trie);
20 void trieAdd(trieNodeT *trie, char *key, int value);
21 trieNodeT* addChild(char key);
22 int trieIsMember(trieCDT trie, char keys[]);
23 int totalStringsWithPrefix(trieCDT trie, char keys[]);
24 void trieDestroy(trieNodeT *root);
25 void test1();
26 void startTesting();
27 void startTestingFromFile(char ** stdip_v);
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "trie.h"
5
6 // To enable debug messages uncomment #define
7 #define TEST 1
8 // To test trie by providing input from file, uncomment 'TESTFROMFILE'
9 // Compile code and while executing provide file name at command line
10 // For e.g. > ./a.out ipFile.txt
11 //
12 //#define TESTFROMFILE 1
13 //
14 // To enable debug messages uncomment 'DEBUG'
15 //#define DEBUG 1
16
17 #ifdef DEBUG
18 # define D(x) x
19 #else
20 # define D(x)
21 #endif
22
23 int main(int argc, char * argv[])
24 {
25 #ifdef TEST
26 startTesting();
27 #endif
28
29 #ifdef TESTFROMFILE
30 startTestingFromFile(argv);
31 #endif
32
33 return 0 ;
34 }
35
36 // Create root node of trie
37 void trieCreate(trieCDT *trie)
38 {
39 trie->root = (trieNodeT*)calloc(1 ,sizeof (trieNodeT));
40
41 if (trie->root == NULL ) {
42 printf(" Can not alloc memory \n " );
43 return ;
44 }
45
46 trie->root->key = '\0' ;
47 trie->root->value = -1 ;
48 trie->root->next = NULL ;
49 trie->root->children = NULL ;
50 }
51
52 // This is recursive function for adding node in trie
53 // It covers 3 cases
54 // Case 1: When only root node is present in a trie. In this
55 // case keep on adding node one level after another.
56 //
57 // If input given is "Good" and if 'G' is not found then
58 // insert 'G' and return 'G' node from where next insertion
59 // has to be done as we have already found there is no
60 // other 'G' exist.
61 //
62 // Case 2: When matching key node is already found return the matching
63 // node and increment key
64 //
65 // Case 3: When key does not match to existing children i.e. for
66 // "abcd", "abef" and "abgh"
67 // . ----> root
68 // |
69 // a
70 // |
71 // b
72 // |
73 // c ===> e ===> g (LL, children of b)
74 // | | |
75 // d f h
76
77
78 void trieAdd(trieNodeT* trie, char *key, int value) {
79
80 // Get root of children
81 if (key == NULL ) {
82 return ;
83 } else if (trie->children == NULL && trie->next == NULL ) {
84
85 // Case 1
86 trieNodeT* child = addChild(*key);
87 trie->children = child;
88
89 if (*key == '\0' ) {
90 child->value = value;
91 child->words++;
92 return ;
93 }
94
95 return trieAdd(child, ++key, value);
96 }
97
98 trieNodeT* level = trie->children;
99 trieNodeT* current;
100 for (current = level; current != NULL ; current = current->next) {
101
102 // Case 2
103 if (current->key == *key) {
104 current->prefix++;
105
106 if (*key == '\0' ) {
107 current->words++;
108 return ;
109 }
110 return trieAdd(current, ++key, value);
111 }
112
113 // This is last element in LL and key is not found
114 // For e.g. for "abc" and "abd", c and d should be
115 // child of b.
116 // Since, c != d, Append d to c in LL signifying they
117 // are both child of 'b' and are on same level
118 //
119 // Case 3
120 if (current->next == NULL ) {
121 //Add key
122 trieNodeT* child = addChild(*key);
123 current->next = child;
124
125 if (*key == '\0' ) {
126 child->words++;
127 child->value = value;
128 return ;
129 }
130
131 return trieAdd(child, ++key, value);
132 }
133 }
134 }
135
136 trieNodeT* addChild(char key)
137 {
138 trieNodeT* child = (trieNodeT*)calloc(1 ,sizeof (trieNodeT));
139
140 if (child == NULL ) {
141 printf(" Can not alloc memory \n " );
142 return NULL ;
143 }
144 child->key = key;
145 child->value = -1 ;
146 child->next = NULL ;
147 child->children = NULL ;
148 child->prefix = 1 ;
149 child->words = 0 ;
150
151 return child;
152 }
153
154 int totalStringsWithPrefix(trieCDT trie, char keys[])
155 {
156 trieNodeT *level = trie.root->children;
157
158 while (keys != NULL ) {
159 trieNodeT *found = NULL ;
160 trieNodeT *current;
161
162 for (current = level; current != NULL ; current = current->next) {
163 if (current->key == *keys) {
164 found = current;
165 break ;
166 }
167 }
168
169 if (found == NULL ) {
170 return 0 ;
171 } else if (*(keys + 1 ) == '\0' ) {
172 return found->prefix;
173 }
174 level = found -> children;
175 keys++;
176 }
177
178 return 0 ;
179 }
180
181 int trieIsMember(trieCDT trie, char keys[])
182 {
183 trieNodeT *level = trie.root->children;
184
185 while (keys != NULL ) {
186 trieNodeT *found = NULL ;
187 trieNodeT *current;
188
189 for (current = level; current != NULL ; current = current->next) {
190 if (current->key == *keys) {
191 found = current;
192 break ;
193 }
194 }
195
196 if (found == NULL ) {
197 return 0 ;
198 } else if (*keys == '\0' ) {
199 return 1 ;
200 }
201 level = found -> children;
202 keys++;
203 }
204
205 return 0 ;
206 }
207
208 void trieDestroy(trieNodeT * root)
209 {
210 if (root->children == NULL && root->next == NULL ) {
211 D(printf(" Destroying %d \n " , root->value));
212 free (root);
213 return ;
214 }
215
216 // If root have next and children free them first
217 if (root->next != NULL ) {
218 trieDestroy(root->next);
219 }
220
221 if (root->children != NULL ) {
222 trieDestroy(root->children);
223 }
224
225 #ifdef DEBUG
226 if (root->key != '\0' ) {
227 printf(" Destroying %c \n " , root->key);
228 } else {
229 printf(" Destroying Root %d \n " , root->value);
230 }
231 #endif
232
233 free (root);
234 }
235
236 void test1()
237 {
238 char s[] = " ABCD " ;
239 char s1[] = " ABCDE " ;
240 int i = 0 ;
241 trieCDT trie;
242 trieCreate(&trie);
243 trieAdd(trie.root, " ABCD " , 20 );
244 trieAdd(trie.root, " ABCDE " , 30 );
245
246 if (trieIsMember(trie, s)) {
247 printf(" Found member 'ABCD' \n " );
248 }
249
250 i = totalStringsWithPrefix(trie, " ABC " );
251 printf(" Total words with prefix 'ABC' %d \n " , i);
252
253 trieDestroy(trie.root);
254 }
255
256 void startTesting()
257 {
258 test1();
259 }
260
261 void startTestingFromFile(char ** stdip_v)
262 {
263 FILE *fp = NULL ;
264 char key[50 ];
265 trieCDT trie;
266 int i = 0 ;
267
268 fp = fopen(stdip_v[1 ], " r " );
269 if (fp == NULL ) {
270 fprintf(stderr, " Can not read file!! \n " );
271 return ;
272 }
273
274 trieCreate(&trie);
275
276 while (fscanf(fp, " %s " , key) != EOF ) {
277 trieAdd(trie.root, key, i);
278 i++;
279
280 if (!trieIsMember(trie, key)) {
281 printf(" Key '%s' NOT found in trie \n " , key);
282 }
283 }
284
285 printf(" Total words inserted in trie %d \n " , i);
286
287 i = totalStringsWithPrefix(trie, " Abe " );
288
289 printf(" Total prefixs with 'Abe' %d \n " , i);
290
291 trieDestroy(trie.root);
292 }
Infix to Postfix
Postfix to Infix
Evaluate Postfix expression
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Some examples:
["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
1
2 class Solution {
3 public:
4 Solution(){};
5 ~Solution() {};
6
7 int evalRPN(vector<string> &tokens) {
8 int num = 0 ;
9 vector<string>::const_iterator cii;
10
11 for (int ii=0 ; ii < tokens.size(); ii++)
12 {
13 num = atoi(tokens.at(ii).c_str());
14 if (!((tokens[ii] == " + " ) || (tokens[ii] == " - " ) ||
15 (tokens[ii] == " * " ) || (tokens[ii] == " / " ))) {
16 mystack.push(num);
17 } else {
18 if (mystack.empty()) {
19 return 0 ;
20 }
21
22 num = mystack.top();
23 mystack.pop();
24
25 if (mystack.empty()) {
26 return 0 ;
27 }
28
29 if (tokens[ii] == " + " ) {
30 num += mystack.top();
31 } else if (tokens[ii] == " - " ) {
32 num = mystack.top() - num;
33 } else if (tokens[ii] == " * " ) {
34 num *= mystack.top();
35 } else if (tokens[ii] == " / " ) {
36 if (num == 0 ) {
37 return 0 ;
38 }
39 num = mystack.top() / num;
40 } else {
41 return 0 ;
42 }
43
44 mystack.pop();
45 mystack.push(num);
46 }
47 }
48
49 return mystack.top();
50 }
51
52 std::stack<int > mystack;
53 };
Tree Problems
Find BST is balanced or not
Balanced tree is defined to be a tree such that no two leaf nodes differ in distance from the root by more than one.
1
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 int arrLen = 5 ;
6 int maxdepth = 0 ;
7 int mindepth = 10 ;
8 int totalElem = 8 ;
9
10 typedef struct BST {
11 int data;
12 struct BST *left;
13 struct BST *right;
14 } nodeBST;
15
16 void balanceBST(int arr[]);
17 nodeBST* addNode(int data);
18 void addNodeToBST(nodeBST *root, nodeBST *node);
19 void traverse(nodeBST *root);
20 void maxDepth(nodeBST *root, int depth);
21 void minDepth(nodeBST *root, int depth);
22
23 int maxDepthWithoutGlobalVar(nodeBST *root, int depth, int maxDeep);
24 int minDepthWithoutGlobalVar(nodeBST *root, int depth, int minDeep);
25
26 int main()
27 {
28 int arr[10 ] = {5 ,3 ,7 ,10 ,6 ,12 ,2 ,1 };
29
30 (void )balanceBST(arr);
31
32 return 0 ;
33 }
34
35 void balanceBST(int arr[])
36 {
37 nodeBST *node;
38 nodeBST *root;
39 int max = 0 ;
40 int min = 100000 ;
41
42 for (int i = 0 ; i < totalElem; i++) {
43 node = addNode(arr[i]);
44 if (node == NULL ) {
45 return ;
46 }
47
48 if (i == 0 ) {
49 root = node;
50 continue ;
51 }
52
53 addNodeToBST(root, node);
54 }
55
56 printf(" Nodes created \n " );
57 traverse(root);
58 maxDepth(root, 0 );
59 printf(" \n Max Depth %d \n " , maxdepth);
60 minDepth(root, 0 );
61 printf(" Min Depth %d \n \n " , mindepth);
62
63 max = maxDepthWithoutGlobalVar(root, 0 , max);
64 printf(" Max Depth %d \n " , max);
65
66 min = minDepthWithoutGlobalVar(root, 0 , min);
67 printf(" Min Depth %d \n " , min);
68
69 if ((max - min) > 1 ) {
70 printf(" Binary search tree is not Balanced \n " );
71 } else {
72 printf(" Binary search tree is Balanced \n " );
73 }
74 }
75
76 nodeBST* addNode(int data)
77 {
78 nodeBST *node = (nodeBST*)calloc(1 , sizeof (nodeBST));
79
80 if (node == NULL ) {
81 return NULL ;
82 }
83
84 node->data = data;
85 node->left = NULL ;
86 node->right = NULL ;
87
88 return node;
89 }
90
91 void addNodeToBST(nodeBST *root, nodeBST *node)
92 {
93 while (root != NULL ) {
94 if (node->data < root->data) {
95 if (root->left != NULL ) {
96 root = root->left;
97 } else {
98 root->left = node;
99 return ;
100 }
101 } else {
102 if (root->right != NULL ) {
103 root = root->right;
104 } else {
105 root->right = node;
106 return ;
107 }
108 }
109 }
110
111 return ;
112 }
113
114 void traverse(nodeBST *root)
115 {
116 if (root == NULL ) {
117 return ;
118 } else {
119 traverse(root->left);
120 printf(" %d " , root->data);
121 traverse(root->right);
122 }
123
124 return ;
125 }
126
127 void maxDepth(nodeBST *root, int depth)
128 {
129 if (root == NULL ) {
130 if (maxdepth < depth) {
131 maxdepth = depth;
132 }
133 } else {
134 maxDepth(root->left, (depth + 1 ));
135 maxDepth(root->right, (depth + 1 ));
136 }
137 }
138
139 void minDepth(nodeBST *root, int depth)
140 {
141 if (root == NULL ) {
142 if (mindepth > depth) {
143 mindepth = depth;
144 }
145 } else {
146 minDepth(root->left, (depth + 1 ));
147 minDepth(root->right, (depth + 1 ));
148 }
149 }
150
151 int maxDepthWithoutGlobalVar(nodeBST *root, int depth, int maxDeep)
152 {
153 if (root == NULL ) {
154 if (maxDeep <= depth) {
155 maxDeep = depth;
156 }
157 return maxDeep;
158 } else {
159 maxDeep = maxDepthWithoutGlobalVar(root->left, (depth + 1 ), maxDeep);
160 maxDeep = maxDepthWithoutGlobalVar(root->right, (depth + 1 ), maxDeep);
161 }
162
163 return maxDeep;
164 }
165
166 int minDepthWithoutGlobalVar(nodeBST *root, int depth, int minDeep)
167 {
168 if (root == NULL ) {
169 if (minDeep >= depth) {
170 minDeep = depth;
171 }
172 return minDeep;
173 } else {
174 minDeep = minDepthWithoutGlobalVar(root->left, (depth + 1 ), minDeep);
175 minDeep = minDepthWithoutGlobalVar(root->right, (depth + 1 ), minDeep);
176 }
177
178 return minDeep;
179 }
Find Binary Tree is BST or not
A binary search tree (BST) is a node based binary tree data structure which has the following properties.
• The left subtree of a node contains only nodes with keys less than the node’s key.
• The right subtree of a node contains only nodes with keys greater than the node’s key.
• Both the left and right subtrees must also be binary search trees.
Method 1
Perform inorder traversal on tree and store it in temporary array. By property of inorder traversal the numbers stored should be sorted sequence of it’s a BST else it’s not BST.
The only caveat is that this method require O(n) space
1
2
3 int temp[TREESIZE];
4
5 void traverse(nodeBST *root)
6 {
7 static int n = 0 ;
8
9 if (root == NULL ) {
10 return ;
11 } else {
12 traverse(root->left);
13 temp[n++] = root->data;
14 traverse1(root->right);
15 }
16
17 return ;
18 }
19
20 for (int i = 0 ; i < TREESIZE; i++) {
21 if (temp[i] > temp [i + 1 ]) {
22 return 0 ; // Binary tree is not BST
23 }
24 }
25 return 1 ;
Method 2
1
2 int isBSTUtil(nodeBST* node, int min, int max);
3
4 /* Returns true if the given tree is a binary search tree
5 (efficient version). */
6 int isBST(nodeBST* node)
7 {
8 return (isBSTUtil(node, INT_MIN, INT_MAX));
9 }
10
11 /* Returns true if the given tree is a BST and its
12 values are >= min and <= max. */
13 int isBSTUtil(nodeBST* node, int min, int max)
14 {
15 /* an empty tree is BST */
16 if (node==NULL )
17 return 1 ;
18
19 /* false if this node violates the min/max constraint */
20 if (node->data < min || node->data > max)
21 return 0 ;
22
23 /* otherwise check the subtrees recursively,
24 tightening the min or max constraint */
25 return
26 isBSTUtil(node->left, min, (node->data - 1 )) && // Allow only distinct values
27 isBSTUtil(node->right, (node->data + 1 ), max); // Allow only distinct values
28 }
BST - Recursive Inorder Traversal
Time complexity O(n) and space complexity is size of stack for function calls
1
2 // Recursive inorder traverse
3 void traverse(nodeBST *root)
4 {
5 if (root == NULL ) {
6 return ;
7 } else {
8 traverse(root->left);
9 printf(" %d " , root->data);
10 traverse(root->right);
11 }
12
13 return ;
14 }
BST - Iterative Inorder Traversal
Time complexity O(n) and space complexity is size of stack
1
2 // Iterative
3 // 1) Create an empty stack S.
4 // 2) Initialize current node as root
5 // 3) Push the current node to S and set current = current->left until curt is NULL
6 // 4) If current is NULL and stack is not empty then$
7 // a) Pop the top item from stack.
8 // b) Print the popped item, set current = current->right
9 // c) Go to step 3.
10 // 5) If current is NULL and stack is empty then we are done.
11
12 void iterativeInorder(nodeBST *root)
13 {
14 createStack();
15
16 while (1 ) {
17 if (root != NULL ) {
18 // Keep pushing in the stack
19 push(root);
20 root = root->left;
21 } else {
22 if (isStackEmpty()) {
23 break ;
24 }
25
26 root = pop();
27 printf(" %d " , root->data);
28
29 root = root->right;
30 }
31 }
32 }
BST - Morris Inorder Traversal
Morris Inorder Traversal run without using recursion and without extra stack space.
Morris Inorder runs in O(NlogN) time and O(1) space
1
2 void MorrisInorder(nodeBST *root) {
3 nodeBST* current,*pre;
4 current=root;
5 while (current!=NULL ) {
6 if (current->left==NULL ) {
7 printf(" %d " ,current->data);
8 current=current->right;
9 }
10 else {
11 pre=current->left;
12 while (pre->right != NULL && pre->right !=current)
13 pre=pre->right;
14 if (pre->right==NULL ) {
15 printf(" Link %d, %d \n " , pre->data, current->data);
16 pre->right=current;
17 current=current->left;
18 }
19 else {
20 pre->right=NULL ;
21 printf(" %d " ,current->data);
22 current=current->right;
23 }
24 }
25 }
26 }