典型應用是用於統計和排序大量的字符串(但不僅限於字符串),
所以經常被搜索引擎系統用於文本詞頻統計。
它的優點是:最大限度地減少無謂的字符串比較,查詢效率比哈希表高。
Trie的核心思想是空間換時間。利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。
Trie是個簡單但實用的數據結構,通常用於實現字典查詢。我們做即時響應用戶輸入的AJAX搜索框時,就是Trie開始。本質上,Trie是一顆存儲多個字符串的樹。相鄰節點間的邊代表一個字符,這樣樹的每條分支代表一則子串,而樹的葉節點則代表完整的字符串。和普通樹不同的地方是,相同的字符串前綴共享同一條分支。還是例子最清楚。
基本操作
1.定義結點
struct node{
int cnt;
struct node *next[26];
node()
{
cnt=0;
memset(next,0,sizeof(next));
}
};
next是表示每層有多少種類的數,如果只是小寫字母,則26即可,若改爲大小寫字母,則是52,若再加上數字,則是62了,這裏根
據題意來確定。
cnt可以表示一個字典樹到此有多少相同前綴的數目,
這裏根據需要應當學會自由變化。
插入(即建樹過程)
構建Trie樹的基本算法也很簡單,無非是逐一把每則單詞的每個字母插入Trie。
插入前先看前綴是否存在。如果存在,就共享,否則
創建對應的節點和邊。比如要插入單詞add(已經插入了單詞“ad”),
就有下面幾步:
考察前綴"a",發現邊a已經存在。於是順着邊a走到節點a。
考察剩下的字符串"dd"的前綴"d",發現從節點a出發,已經有邊d存在。
於是順着邊d走到節點ad
考察最後一個字符"d",這下從節點ad出發沒有邊d了,
於是創建節點ad的子節點add,並把邊ad->add標記爲d。
void buildtree(char *s)
{
node *p=root;
node *tmp=NULL;
int l=strlen(s);
for(int i=0;i<l;i++)
{
if(p->next[s[i]-'a']==NULL)
{
tmp=new node;
p->next[s[i]-'a']=tmp;
}
p=p->next[s[i]-'a'];
p->cnt++;
}
}
查找
(1)每次從根結點開始進行搜索;
(2)取要查找關鍵詞的第一個字母,
並根據該字母選擇對應的子樹並轉到該子樹繼續進行檢索;
(3)在相應的子樹上,取得要查找關鍵詞的第二個字母,
並進一步選擇對應的子樹進行檢索;
(4)迭代剛纔過程。。。
(5)直到在某個結點處:
——關鍵詞的所有字母都被取出,則讀取附在該結點上的信息,即完成查找。
——該結點沒有任何信息,則輸出該關鍵詞不在此字典樹裏。
void findtire(char *s)
{
node *p=root;
int l=strlen(s);
for(int i=0;i<l;i++)
{
if(p->next[s[i]-'a']==NULL)
{
printf("0\n");
return;
}
p=p->next[s[i]-'a'];
}
printf("%d\n",p->cnt);
}
釋放內存
有些題目,數據比較大,需要查詢完之後釋放內存
void del(node *root)
{
for(int i=0;i<10;i++)
if(root->next[i])
del(root->next[i]);
delete(root);
}