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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构之Trie树

發(fā)布時間:2025/3/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构之Trie树 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1、 概述

Trie樹,又稱字典樹,單詞查找樹或者前綴樹,是一種用于快速檢索的多叉樹結(jié)構,如英文字母的字典樹是一個26叉樹,數(shù)字的字典樹是一個10叉樹。

Trie一詞來自retrieve,發(fā)音為/tri:/ “tree”,也有人讀為/tra?/ “try”。

Trie樹可以利用字符串的公共前綴來節(jié)約存儲空間。如下圖所示,該trie樹用10個節(jié)點保存了6個字符串tea,ten,to,in,inn,int:

在該trie樹中,字符串in,inn和int的公共前綴是“in”,因此可以只存儲一份“in”以節(jié)省空間。當然,如果系統(tǒng)中存在大量字符串且這些字符串基本沒有公共前綴,則相應的trie樹將非常消耗內(nèi)存,這也是trie樹的一個缺點。

Trie樹的基本性質(zhì)可以歸納為:

(1)根節(jié)點不包含字符,除根節(jié)點意外每個節(jié)點只包含一個字符。

(2)從根節(jié)點到某一個節(jié)點,路徑上經(jīng)過的字符連接起來,為該節(jié)點對應的字符串。

(3)每個節(jié)點的所有子節(jié)點包含的字符串不相同。

2、 Trie樹的基本實現(xiàn)

字母樹的插入(Insert)、刪除( Delete)和查找(Find)都非常簡單,用一個一重循環(huán)即可,即第i 次循環(huán)找到前i 個字母所對應的子樹,然后進行相應的操作。實現(xiàn)這棵字母樹,我們用最常見的數(shù)組保存(靜態(tài)開辟內(nèi)存)即可,當然也可以開動態(tài)的指針類型(動態(tài)開辟內(nèi)存)。至于結(jié)點對兒子的指向,一般有三種方法:

1、對每個結(jié)點開一個字母集大小的數(shù)組,對應的下標是兒子所表示的字母,內(nèi)容則是這個兒子對應在大數(shù)組上的位置,即標號;

2、對每個結(jié)點掛一個鏈表,按一定順序記錄每個兒子是誰;

3、使用左兒子右兄弟表示法記錄這棵樹。

三種方法,各有特點。第一種易實現(xiàn),但實際的空間要求較大;第二種,較易實現(xiàn),空間要求相對較小,但比較費時;第三種,空間要求最小,但相對費時且不易寫。

下面給出動態(tài)開辟內(nèi)存的實現(xiàn):

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 #define MAX_NUM 26 enumNODE_TYPE{ //"COMPLETED" means a string is generated so far. ??COMPLETED, ??UNCOMPLETED }; structNode { ??enumNODE_TYPE type; ??charch; ??structNode* child[MAX_NUM]; //26-tree->a, b ,c, .....z }; structNode* ROOT; //tree root structNode* createNewNode(charch){ ??// create a new node ??structNode *new_node = (structNode*)malloc(sizeof(structNode)); ??new_node->ch = ch; ??new_node->type == UNCOMPLETED; ??inti; ??for(i = 0; i < MAX_NUM; i++) ????new_node->child[i] = NULL; ??returnnew_node; } voidinitialization() { //intiazation: creat an empty tree, with only a ROOT ROOT = createNewNode(' '); } intcharToindex(charch) { //a "char" maps to an index<br> returnch - 'a'; } intfind(constchar chars[], intlen) { ??structNode* ptr = ROOT; ??inti = 0; ??while(i < len) { ???if(ptr->child[charToindex(chars[i])] == NULL) { ???break; ??} ??ptr = ptr->child[charToindex(chars[i])]; ??i++; ??} ??return(i == len) && (ptr->type == COMPLETED); } voidinsert(constchar chars[], intlen) { ??structNode* ptr = ROOT; ??inti; ??for(i = 0; i < len; i++) { ???if(ptr->child[charToindex(chars[i])] == NULL) { ????ptr->child[charToindex(chars[i])] = createNewNode(chars[i]); ??} ??ptr = ptr->child[charToindex(chars[i])]; } ??ptr->type = COMPLETED; }

3、 Trie樹的高級實現(xiàn)

可以采用雙數(shù)組(Double-Array)實現(xiàn)。利用雙數(shù)組可以大大減小內(nèi)存使用量,具體實現(xiàn)細節(jié)見參考資料(5)(6)。

4、 Trie樹的應用

Trie是一種非常簡單高效的數(shù)據(jù)結(jié)構,但有大量的應用實例。

(1) 字符串檢索

事先將已知的一些字符串(字典)的有關信息保存到trie樹里,查找另外一些未知字符串是否出現(xiàn)過或者出現(xiàn)頻率。

舉例:

@? 給出N 個單詞組成的熟詞表,以及一篇全用小寫英文書寫的文章,請你按最早出現(xiàn)的順序?qū)懗鏊胁辉谑煸~表中的生詞。

@? 給出一個詞典,其中的單詞為不良單詞。單詞均為小寫字母。再給出一段文本,文本的每一行也由小寫字母構成。判斷文本中是否含有任何不良單詞。例如,若rob是不良單詞,那么文本problem含有不良單詞。

(2)字符串最長公共前綴

Trie樹利用多個字符串的公共前綴來節(jié)省存儲空間,反之,當我們把大量字符串存儲到一棵trie樹上時,我們可以快速得到某些字符串的公共前綴。

舉例:

@ 給出N 個小寫英文字母串,以及Q 個詢問,即詢問某兩個串的最長公共前綴的長度是多少?

解決方案:首先對所有的串建立其對應的字母樹。此時發(fā)現(xiàn),對于兩個串的最長公共前綴的長度即它們所在結(jié)點的公共祖先個數(shù),于是,問題就轉(zhuǎn)化為了離線(Offline)的最近公共祖先(Least Common Ancestor,簡稱LCA)問題。

而最近公共祖先問題同樣是一個經(jīng)典問題,可以用下面幾種方法:

1. 利用并查集(Disjoint Set),可以采用采用經(jīng)典的Tarjan 算法;

2. 求出字母樹的歐拉序列(Euler Sequence )后,就可以轉(zhuǎn)為經(jīng)典的最小值查詢(Range Minimum Query,簡稱RMQ)問題了;

(關于并查集,Tarjan算法,RMQ問題,網(wǎng)上有很多資料。)

(3)排序

Trie樹是一棵多叉樹,只要先序遍歷整棵樹,輸出相應的字符串便是按字典序排序的結(jié)果。

舉例:

@ 給你N 個互不相同的僅由一個單詞構成的英文名,讓你將它們按字典序從小到大排序輸出。

(4) 作為其他數(shù)據(jù)結(jié)構和算法的輔助結(jié)構

如后綴樹,AC自動機等

5、 Trie樹復雜度分析

(1) 插入、查找的時間復雜度均為O(N),其中N為字符串長度。

(2) 空間復雜度是26^n級別的,非常龐大(可采用雙數(shù)組實現(xiàn)改善)。

6、 總結(jié)

Trie樹是一種非常重要的數(shù)據(jù)結(jié)構,它在信息檢索,字符串匹配等領域有廣泛的應用,同時,它也是很多算法和復雜數(shù)據(jù)結(jié)構的基礎,如后綴樹,AC自動機等,因此,掌握Trie樹這種數(shù)據(jù)結(jié)構,對于一名IT人員,顯得非常基礎且必要!

7、 參考資料

(1)wiki:http://en.wikipedia.org/wiki/Trie

(2) 博文《字典樹的簡介及實現(xiàn)》:

http://hi.baidu.com/luyade1987/blog/item/2667811631106657f2de320a.html

(3) 論文《淺析字母樹在信息學競賽中的應用》

(4)? 論文《Trie圖的構建、活用與改進》

(5)? 博文《An Implementation of Double-Array Trie》:

http://linux.thai.net/~thep/datrie/datrie.html

(6) 論文《An Efficient Implementation of Trie Structures》:

http://www.google.com.hk/url?sa=t&source=web&cd=4&ved=0CDEQFjAD&url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.14.8665%26rep%3Drep1%26type%3Dpdf&ei=qaehTZiyJ4u3cYuR_O4B&usg=AFQjCNF5icQbRO8_WKRd5lMh-eWFIty_fQ&sig2=xfqSGYHBKqOLXjdONIQNVw

————————————————————————————————————-

更多關于數(shù)據(jù)結(jié)構和算法的介紹,請查看:數(shù)據(jù)結(jié)構與算法匯總

————————————————————————————————————-

原創(chuàng)文章,轉(zhuǎn)載請注明:?轉(zhuǎn)載自董的博客

本文鏈接地址:?http://dongxicheng.org/structure/trietree/

總結(jié)

以上是生活随笔為你收集整理的数据结构之Trie树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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