在計(jì)算機(jī)科學(xué)中,Trie樹(發(fā)音為“try”或“tree”),也叫前綴樹或字典樹,是一種有序樹,用于存儲(chǔ)關(guān)聯(lián)數(shù)組,其中鍵通常是字符串。與二叉查找樹不同,鍵不是直接存儲(chǔ)在節(jié)點(diǎn)中,而是在樹的路徑上從根到表示鍵的節(jié)點(diǎn)所經(jīng)過的邊上存儲(chǔ)。例如,鍵“yes”存儲(chǔ)在從根節(jié)點(diǎn)到“y”,從“y”到“e”,從“e”到“s”的路徑上。
PHP中的Trie樹是一個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu),它可以用來快速定位查找字符串,比如“自動(dòng)補(bǔ)全”或“模糊查找”等場(chǎng)景。下面我們來看一個(gè)簡(jiǎn)單的例子,假設(shè)我們有一個(gè)字符串?dāng)?shù)組,存儲(chǔ)了一些搜索關(guān)鍵詞:
$words = array( 'apple', 'banana', 'orange', 'pear', 'peach', 'grape' );
我們現(xiàn)在想要實(shí)現(xiàn)一個(gè)自動(dòng)補(bǔ)全功能,即用戶在輸入框中輸入一個(gè)字符,我們根據(jù)這個(gè)字符來搜索匹配的關(guān)鍵詞,然后返回一個(gè)下拉列表供用戶選擇。我們可以使用Trie樹來完成這個(gè)功能,下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn):
class TrieNode { public $children = array(); public $isEnd = false; } class Trie { private $root; public function __construct() { $this->root = new TrieNode(); } public function insert($word) { $node = $this->root; for ($i = 0; $i < strlen($word); $i++) { $char = $word[$i]; if (!isset($node->children[$char])) { $node->children[$char] = new TrieNode(); } $node = $node->children[$char]; } $node->isEnd = true; } public function search($word) { $node = $this->root; for ($i = 0; $i < strlen($word); $i++) { $char = $word[$i]; if (!isset($node->children[$char])) { return false; } $node = $node->children[$char]; } return $node->isEnd; } public function startsWith($prefix) { $node = $this->root; for ($i = 0; $i < strlen($prefix); $i++) { $char = $prefix[$i]; if (!isset($node->children[$char])) { return false; } $node = $node->children[$char]; } return true; } } $tree = new Trie(); foreach ($words as $word) { $tree->insert($word); } if ($tree->startsWith('a')) { echo 'Found matches!'; }
在上面的代碼中,我們首先定義了一個(gè)TrieNode類,其中$children數(shù)組用來存儲(chǔ)子節(jié)點(diǎn),$isEnd表示當(dāng)前節(jié)點(diǎn)是否為某個(gè)字符串的結(jié)束節(jié)點(diǎn)。然后我們定義了一個(gè)Trie類,其中$root是一個(gè)根節(jié)點(diǎn),insert()方法用來向Trie中插入一個(gè)字符串,search()方法用來查找一個(gè)字符串是否存在于Trie中,startsWith()方法用來查找以指定前綴開頭的所有字符串。最后我們創(chuàng)建了一個(gè)Trie實(shí)例,并將$words數(shù)組中的所有字符串插入到Trie中,然后使用startsWith()方法查找以字母“a”開頭的所有字符串。
通過上面的例子,我們可以看到Trie樹的一些優(yōu)勢(shì),它可以快速地完成字符串匹配,而不需要遍歷整個(gè)字符串?dāng)?shù)組;它可以非常高效地存儲(chǔ)大量字符串,并且可以快速地查找任何一個(gè)字符串。不過需要注意的是,在實(shí)際應(yīng)用中,Trie樹的空間復(fù)雜度比較高,因?yàn)槊總€(gè)節(jié)點(diǎn)都需要存儲(chǔ)一些額外的信息,占用了很多空間。所以在使用Trie樹時(shí)需要注意字符串?dāng)?shù)量,盡量避免存儲(chǔ)太多的字符串。