日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

海量数据处理-Trie树

發(fā)布時(shí)間:2025/3/20 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 海量数据处理-Trie树 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/beiyeqingteng/article/details/6981263

http://blog.csdn.net/zmazon/article/details/8227610#

關(guān)注Trie 這種結(jié)構(gòu)已經(jīng)很久,Trie有一個(gè)很有趣的用途,那就是自動(dòng)提示。而且,前不久在一次面試?yán)?#xff0c;也需要用Trie來解答。所以,在此對(duì)這個(gè)數(shù)據(jù)結(jié)構(gòu)進(jìn)行總結(jié)。

Trie,又稱單詞查找樹或鍵樹,是一種樹形結(jié)構(gòu)。典型應(yīng)用是用于統(tǒng)計(jì)和排序大量的字符串(但不僅限于字符串),所以經(jīng)常被搜索引擎系統(tǒng)用于文本詞頻統(tǒng)計(jì)。它的優(yōu)點(diǎn)是:最大限度地減少無謂的字符串比較,查詢效率比哈希表高。
它有3個(gè)基本性質(zhì):

1,根節(jié)點(diǎn)不包含字符,除根節(jié)點(diǎn)外每一個(gè)節(jié)點(diǎn)都只包含一個(gè)字符。
2,從根節(jié)點(diǎn)到某一節(jié)點(diǎn),路徑上經(jīng)過的字符連接起來,為該節(jié)點(diǎn)對(duì)應(yīng)的字符串。
3,每個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)包含的字符都不相同。

下面這個(gè)圖就是Trie的表示,每一條邊表示一個(gè)字符,如果結(jié)束,就用星號(hào)表示。在這個(gè)Trie結(jié)構(gòu)里,我們有下面字符串,比如do, dork, dorm等,但是Trie里沒有ba, 也沒有sen,因?yàn)樵赼, 和n結(jié)尾,沒有結(jié)束符號(hào)(星號(hào))。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


我們來看看Trie樹的特點(diǎn):根節(jié)點(diǎn)為空值,剩下每一個(gè)節(jié)點(diǎn)保存一個(gè)字母。知道這些就夠了!

我們?cè)賮砜纯催@棵樹能干什么?如果從根節(jié)點(diǎn)遍歷到某一個(gè)節(jié)點(diǎn)把路徑節(jié)點(diǎn)的值連在一起就構(gòu)成了一個(gè)字符串,利用這個(gè)特點(diǎn)很容易想到這棵樹的第一個(gè)功能能幫我們查找某一個(gè)單詞是否在樹中(需要在每一個(gè)節(jié)點(diǎn)設(shè)置一個(gè)標(biāo)志,表示從根節(jié)點(diǎn)到此節(jié)點(diǎn)是否構(gòu)成一個(gè)單詞);如果該單詞存在,我們可以利用它實(shí)現(xiàn)第二個(gè)功能:去除重復(fù)單詞;同樣如果該詞存,在我們還可以看出它的第三個(gè)功能:統(tǒng)計(jì)單詞頻率;因?yàn)檫@是一個(gè)樹形結(jié)構(gòu)我們利用這個(gè)特點(diǎn)很容易看出它的第四個(gè)功能能幫我們查找N個(gè)單詞的最長(zhǎng)公共前綴;如果我們按順序遍歷輸出整棵樹,發(fā)現(xiàn)它的第五個(gè)功能:對(duì)字符串排序。


這棵樹創(chuàng)建看起來比較容易,就有一個(gè)問題需要我們考慮:父節(jié)點(diǎn)如何保存孩子節(jié)點(diǎn)? 主要有兩種方式供大家參考:

1.因?yàn)槭怯⑽淖址?#xff0c;我們可以用Node[26]來保存孩子節(jié)點(diǎn)(如果是數(shù)字我們可以用Node[10]),這種方式最快,但是并不是所有節(jié)點(diǎn)都會(huì)有很多孩子,所以這種方式浪費(fèi)的空間太多

2.用一個(gè)鏈表根據(jù)需要?jiǎng)討B(tài)添加節(jié)點(diǎn)。這樣我們就可以省下不小的空間,但是缺點(diǎn)是搜索的時(shí)候需要遍歷這個(gè)鏈表,增加了時(shí)間復(fù)雜度。

class TrieNode{//結(jié)點(diǎn)類private static final int NUMBER = 26;private char _value;private boolean _isWord;//從根節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)存不存在一個(gè)單詞TrieNode[] _children = new TrieNode[NUMBER];//子結(jié)點(diǎn)集合public TrieNode(char c) {this.setValue(c);}public char getValue() {return _value;}public void setValue(char _value) {this._value = _value;}public boolean isWord() {return _isWord;}public void setIsWord(boolean _isWord) {this._isWord = _isWord;}}public class TrieTree {static String[] _words = {"add","am","good","the","think"};//待插入單詞private boolean searchWord(TrieNode _root, String _word) {if(null == _root || null == _word || "".equals(_word))return false;char[] cs = _word.toCharArray();//將字符串轉(zhuǎn)化為字符數(shù)組for(int i = 0; i < cs.length; i++){int index;if(cs[i] >= 'A' && cs[i] <= 'Z'){index = cs[i]-'A';}else if(cs[i] >= 'a' && cs[i] <= 'z') index = cs[i] - 'a';elsereturn false;TrieNode child_node = _root._children[index];if(null != child_node){//找到相同字符if(child_node.isWord())//如果找到該單詞return true;} if(null == child_node)//如果在i層沒找到相同字符 return false;_root = child_node;//重設(shè)根節(jié)點(diǎn)}return false;}private void insertIntoTree(TrieNode _root, String _word) {//插入一個(gè)單詞if(null == _root || null == _word || "".equals(_word))return;char[] cs = _word.toCharArray();//將字符串轉(zhuǎn)化為字符數(shù)組for(int i = 0; i < cs.length; i++){int index;//對(duì)應(yīng)的索引值if(cs[i] >= 'A' && cs[i] <= 'Z'){index = cs[i]-'A';}else if(cs[i] >= 'a' && cs[i] <= 'z') index = cs[i] - 'a';elsereturn;TrieNode child_node = _root._children[index];if(null == child_node){//如果沒找到TrieNode new_node = new TrieNode(cs[i]);//創(chuàng)建新節(jié)點(diǎn)if(i == cs.length-1)//如果遍歷到該單詞最后一個(gè)字符new_node.setIsWord(true);//把該單詞存在樹中_root._children[index] = new_node;//連接該節(jié)點(diǎn)_root = new_node;}else_root = child_node;//更新樹根}}private void printTree(TrieNode _root,char[] _word,int index) {if(_root == null)return;if(_root.isWord()){//如果根節(jié)點(diǎn)到此節(jié)點(diǎn)構(gòu)成一個(gè)單詞則輸出for(char c : _word){if(c != ' ')System.out.print(c);}System.out.println();}for(TrieNode node : _root._children){//遍歷樹根孩子節(jié)點(diǎn)if(node != null){//回溯法遍歷該樹_word[index++] = node.getValue();printTree(node,_word,index);_word[index] = ' ';index--;}}}public static void main(String[] args){TrieTree _tree = new TrieTree();//創(chuàng)建一棵樹TrieNode _root = new TrieNode(' ');//創(chuàng)建根節(jié)點(diǎn)for(String word : _words)//插入單詞_tree.insertIntoTree(_root,word);char[] _word = new char[20];_tree.printTree(_root,_word,0);//打印樹中單詞boolean status = _tree.searchWord(_root,"think");//查詢樹中是否存在某單詞System.out.println(status);} }

總結(jié)

以上是生活随笔為你收集整理的海量数据处理-Trie树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。