對於搜索字符串的需求,在最壞的狀況下,二叉搜索樹的時間複雜度可能爲 O(n),「n」 是二叉樹中存儲的字符串的總數量。因此爲了在最佳時間內搜索字符串,須要一種性能更好的數據結構。Trie 樹(又名單詞搜索樹)能夠避免在搜索字符串時遍歷整個樹。僅包含字母的字符串會把 trie 節點的子級數量限制爲 26。這樣搜索字符串的時間複雜度爲 O(s),其中 「s」 爲字符串的長度。與二進制搜索樹相比,trie 樹在搜索字符串方面效率更高。javascript
trie 樹中單個節點的結構由長度爲 26 的數組和一個布爾值組成,這個布爾值用來標識其是否爲葉子節點。此外,葉子節點能夠具備整數值或映射到字符串的其餘類型的值。數組中的每一個索引表明從 a 到 z 的字母,而且每一個索引能夠有一個 TrieNode 實例。
html
trie node
上圖表示 trie 樹中的根節點。前端
該實現包含兩個類,一個用於 trie 節點,另外一個用於 trie 樹。實現的語言是帶有 ES6 規範的 JavaScript。java
TrieNode 類的屬性爲value,isEnd和 arr。變量 arr 是長度爲 26 的數組,其中填充了 null 值。node
1class TrieNode { 2 constructor() { 3 this.value = undefined; 4 this.isEnd = false; 5 this.arr = new Array(26).fill(null); 6 } 7}
TrieTree 類具備 insert、searchNode、startsWith、printString 和 getRoot 方法。能夠用 startsWith 方法執行前綴搜索。insert方法將字符串和值做爲參數。數組
1class TrieTree { 2 3 constructor() { 4 this.root = new TrieNode(); 5 } 6 7 insert(word, value) { 8 let node = this.root; 9 for (let i = 0; i < word.length; i++) { 10 const index = parseInt(word[i], 36) - 10; 11 12 if (node.arr[index] === null) { 13 const temp = new TrieNode(); 14 node.arr[index] = temp; 15 node = temp; 16 } else { 17 node = node.arr[index]; 18 } 19 } 20 node.isEnd = true; 21 node.value = value; 22 } 23 24 getRoot() { 25 return this.root; 26 } 27 28 startsWith(prefix) { 29 const node = this.searchNode(prefix); 30 if (node == null) { 31 return false; 32 } else { 33 this.printStrings(node, ""); 34 return true; 35 } 36 } 37 38 printStrings(node, prefix) { 39 if (node.isEnd) console.log(prefix); 40 for (let i = 0; i < node.arr.length; i++) { 41 if (node.arr[i] !== null) { 42 const character = String.fromCharCode('a'.charCodeAt() + i); 43 this.printStrings(node.arr[i], prefix + "" + (character)); 44 } 45 } 46 } 47 48 searchNode(str) { 49 let node = this.root; 50 for (let i = 0; i < str.length; i++) { 51 const index = parseInt(str[i], 36) - 10; 52 if (node.arr[index] !== null) { 53 node = node.arr[index]; 54 } else { 55 return null; 56 } 57 } 58 59 if (node === this.root) 60 return null; 61 62 return node; 63 } 64}
下面的代碼顯示瞭如何實例化 「TrieTree」 類,還演示了各類方法的用法。數據結構
1const trieTree = new TrieTree(); 2trieTree.insert("asdfasdf", 5); 3trieTree.insert("cdfasdfas", 23); 4trieTree.insert("cdfzsvljsdf", 42); 5 6let answer = trieTree.searchNode("asdfasdf"); 7console.log(answer.value); //5 8answer = trieTree.startsWith("cdf"); 9console.log(answer); 10//asdfas 11//zsvljsdf 12//true
不一樣方法的時間和空間複雜度以下:ide
searchNode:時間複雜度:O(s),'s' 是字符串的長度,空間複雜度:O(1),由於沒有使用額外的數據結構,例如隊列或棧。post
insert:時間複雜度:O(s),「s」是字符串長度,空間複雜度:O(ns),其中 「n」 是 trie 樹中 key 的數量,「s」 是字符串的長度。性能
在前端開發中,trie 樹可用於如下程序:
自動完成和提早輸入功能。
拼寫檢查。
搜索。
此外 trie 樹能夠用來存儲電話號碼、IP地址和對象等。
原文:https://www.softnami.com/posts_pr/trie-tree-with-javascript.html