trie樹常用於搜索提示。如當輸入一個網址,可以自動搜索出可能的選擇。當沒有完全匹配的搜索結果,可以返回前綴最相似的可能。
一、Tire樹的基本性質
- 根節點不包含字符,除根節點外每一個節點都只包含一個字符。
- 從根節點到某一節點,路徑上經過的字符連接起來,為該節點對應的字符串。
- 每個節點的所有子節點包含的字符都不相同。
Trie 樹的本質,就是利用字符串之間的公共前綴,將重復的前綴合並在一起,比如我們有[b,abc,abd,bcd,abcd,efg,hii ]這個字符串集合,可以將其構建成下面這棵 Trie 樹:
每個節點表示一個字符串中的字符,從根節點到紅色節點的一條路徑表示一個字符串(紅色節點表示是某個單詞的結束字符,但不一定都是葉子節點)。這樣,我們就可以通過遍歷這棵樹來檢索是否存在待匹配的字符串了
二、如何實現Tire樹
Tire主要包含兩個操作,一個是將字符串集合構造成 Trie 樹。這個過程分解開來的話,就是一個將字符串插入到 Trie 樹的過程。另一個是在 Trie 樹中查詢一個字符串。
Trie 樹是個多叉樹,在這里用數組來存儲一個節點的所有子結點。
Trie樹節點類,PHP代碼實現:
1 <?php 2 /** 3 * TrieNode.php 4 * Created on 2019/4/29 14:53 5 * Created by Wilin 6 */ 7 8 class TrieNode 9 { 10 public $data; 11 public $children = []; 12 public $isEndingChar = false; 13 14 public function __construct($data) 15 { 16 $this->data = $data; 17 } 18 }
Trie樹,PHP代碼實現:
1 <?php 2 /** 3 * Tire.php 4 * Created on 2019/4/29 14:57 5 * Created by Wilin 6 */ 7 8 include "TrieNode.php"; 9 10 class Tire { 11 private $root; 12 13 public function __construct() { 14 $this->root = new TrieNode('/'); //根節點 15 } 16 17 public function getRoot() { 18 return $this->root; 19 } 20 21 public function insert($text) { 22 $p = $this->root; 23 for ($i = 0; $i < mb_strlen($text); $i++) { 24 $index = $data = $text[$i]; 25 26 if (empty($p->children[$index])) { 27 $newNode = new TrieNode($data); 28 $p->children[$index] = $newNode; 29 } 30 $p = $p->children[$index]; 31 } 32 $p->isEndingChar = true; 33 } 34 35 public function find($pattern) { 36 $p = $this->root; 37 for ($i = 0; $i < mb_strlen($pattern); $i++) { 38 $index = $data = $pattern[$i]; 39 40 if (empty($p->children[$index])) { 41 return false; 42 } 43 $p = $p->children[$index]; 44 } 45 if ($p->isEndingChar == false) { 46 return false; 47 } 48 return true; 49 } 50 } 51 52 $trie = new Tire(); 53 $strings = ['b','abc','abd','bcd','abcd','efg','hii']; 54 foreach ($strings as $str) { 55 $trie->insert($str); 56 } 57 if ($trie->find('bcd')) { 58 print "包含這個字符串\n"; 59 } else { 60 print "不包含這個字符串\n"; 61 } 62 print_r($trie->getRoot());
打印結果如下:
E:\www\tree\3>php Tire.php 包含這個字符串 TrieNode Object ( [data] => / [children] => Array ( [b] => TrieNode Object ( [data] => b [children] => Array ( [c] => TrieNode Object ( [data] => c [children] => Array ( [d] => TrieNode Object ( [data] => d [children] => Array ( ) [isEndingChar] => 1 ) ) [isEndingChar] => ) ) [isEndingChar] => 1 ) [a] => TrieNode Object ( [data] => a [children] => Array ( [b] => TrieNode Object ( [data] => b [children] => Array ( [c] => TrieNode Object ( [data] => c [children] => Array ( [d] => TrieNode Object ( [data] => d [children] => Array ( ) [isEndingChar] => 1 ) ) [isEndingChar] => 1 ) [d] => TrieNode Object ( [data] => d [children] => Array ( ) [isEndingChar] => 1 ) ) [isEndingChar] => ) ) [isEndingChar] => ) [e] => TrieNode Object ( [data] => e [children] => Array ( [f] => TrieNode Object ( [data] => f [children] => Array ( [g] => TrieNode Object ( [data] => g [children] => Array ( ) [isEndingChar] => 1 ) ) [isEndingChar] => ) ) [isEndingChar] => ) [h] => TrieNode Object ( [data] => h [children] => Array ( [i] => TrieNode Object ( [data] => i [children] => Array ( [i] => TrieNode Object ( [data] => i [children] => Array ( ) [isEndingChar] => 1 ) ) [isEndingChar] => ) ) [isEndingChar] => ) ) [isEndingChar] => )
參考資料:https://www.cnblogs.com/luosongchao/p/3239521.html,https://articles.zsxq.com/id_qa0npqvszcmx.html