-
Notifications
You must be signed in to change notification settings - Fork 130
/
Copy pathtrie.js
158 lines (129 loc) · 3.01 KB
/
trie.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
class Node {
constructor(data) {
this._isLeaf = false;
this._children = {};
this._data = data;
}
get isLeaf() {
return this._isLeaf;
}
set isLeaf(val) {
this._isLeaf = val;
}
get children() {
return this._children;
}
get data() {
return this._data;
}
set data(val) {
this._data = val;
}
}
/**
* Class for Trie
*/
class Trie {
constructor() {
/** @private */
this._root = new Node();
/** @private */
this._size = 0;
}
/**
* Get size of Trie
* @return {Number} Size of Trie
* @public
*/
get size() {
return this._size;
}
/**
* Checks if trie is empty or not
* @return {Boolean} true if empty else false
* @public
*/
isEmpty() {
return Object.keys(this._root.children).length === 0;
}
/**
* Inserts data into trie
* @param {String} data String to be inserted
* @param {*} val Leaf node value
* @return {Node} Inserted node in trie
* @public
*/
insert(data, val = undefined) {
let crawler = this._root;
for (let i = 0; i < data.length; i += 1) {
let child = crawler.children[data[i]];
if (child === undefined) {
child = new Node();
crawler.children[data[i]] = child;
}
crawler = child;
}
this._size += 1;
crawler.isLeaf = true;
crawler.data = val;
return crawler;
}
/**
* Searches and returns whether word exists in trie
* @param {String} data Data to be searched
* @return {*} val of leaf node, if exist else false
* @public
*/
search(data) {
let crawler = this._root;
for (let i = 0; i < data.length; i += 1) {
const child = crawler.children[data[i]];
if (child === undefined) {
return -1;
}
crawler = child;
}
if (crawler !== undefined && crawler.isLeaf) {
return crawler.data;
}
return -1;
}
/**
* Recursively deletes word from the trie
* @param {Node} node Current node being explored
* @param {String} data Word to be deleted
* @param {Integer} level Depth looked in trie
* @param {Integer} length Length of word
* @return {Boolean} true if deleted else false
* @private
*/
_remove(node, data, level, length) {
if (node && level === length && node.isLeaf) {
node.isLeaf = false;
if (Object.keys(node.children).length === 0) {
return true;
}
return false;
}
const index = data[level];
if (this._remove(node.children[index], data, level + 1, length)) {
delete node.children[index];
return (!node.isLeaf && Object.keys(node.children).length === 0);
}
return false;
}
/**
* Word to be deleted
* @param {String} data Word to be deleted
* @return {Boolean} true if deleted else false
* @private
*/
delete(data) {
if (this.search(data) !== -1) {
this._size -= 1;
return this._remove(this._root, data, 0, data.length);
}
return false;
}
}
module.exports = Trie;