樹學習,學習網
字典樹,又稱為字母數,首碼樹等等,不僅可以儲存字元,還可以儲存數字等,
又稱單詞尋找樹,Trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文本詞頻統計。
它的優點是:利用字串的公用首碼來節約儲存空間,最大限度地減少無謂的字串比較,查詢效率比雜湊表高。 字典樹與字典很相似,當你要查一個單詞是不是在字典樹中,首先看單詞的第一個字母是不是在字典的第一層,如果不在,說明字典樹裡沒有該單詞,如果在就在該字母的孩子節點裡找是不是有單詞的第二個字母,沒有說明沒有該單詞,有的話用同樣的方法繼續尋找.字典樹不僅可以用來儲存字母,也可以儲存數字等其它資料
節點結構:
每個節點對應一個最大可儲存字元數組。假設字典只存26個小寫英文字母,那麼每個節點下應該有一個長度為26的數組。換言說,可存的元素類型越多,單個節點佔用記憶體越大。如果用字典樹儲存漢字,那麼每個節點必須為數千個常用漢字開闢一個數組作為儲存空間,佔用的記憶體實在不是一個數量級。不過Trie樹就是一種用空間換時間的資料結構,魚和熊掌往往不可兼得。
建樹細節:
- 取要插入字串的首個字元,從根節點的孩子節點開始,匹配當前字元是否已有節點,有則把指標指向該節點。無則為該字元建立節點,並把指標指向該建立節點。
- 迭代。
- 遇到要插入字串末尾結束符時停止迭代,並把最後一個非’\0’字元對應的節點設為末端節點。
尋找細節:
迴圈取要插入字串的首個字元,從根節點的孩子節點開始,匹配當前字元是否已有節點,有則繼續迴圈,無則返回False. 直至匹配到最後一個字元則完成尋找。
樹結構圖:
我們用apps, apply, apple, append, back, basic, backen幾英文單詞建立樹形結構:
很容易看出,有相同首碼的英文單詞,會合并在同一個節點,Trie樹順著一個個節點進行檢索,
代碼:
#include <stdio.h>
#include <string.h>
#define MAXN 100000
typedef struct TrieNode{
int nCount;
struct TrieNode *next[26];
}TrieNode;
TrieNode Memory[MAXN];
int allocp = 0;
void Init(TrieNode **pRoot)
{
*pRoot = NULL;
}
TrieNode *Build()
{
int i;
TrieNode *p;
p = &Memory[allocp++];
p -> nCount = 1;
for(int i = 0; i < 26; ++i)
{
p->next[i] = NULL;
}
return p;
}
void Insert(TrieNode **pRoot, char *s)
{
int i, k;
TrieNode *p;
if(!(p = *pRoot))
{
p = *pRoot = Build();
}
i = 0;
while(s[i])
{
k = s[i++] - 'a';
if(!p->next[k])
{
p->next[k] = Build();
}
else
{
p->next[k] -> nCount++;
}
p = p->next[k];
}
}
int Search(TrieNode **pRoot, char *s)
{
int k;
TrieNode *p;
p = *pRoot;
int i = 0;
while(p && s[i])
{
k = s[i++] - 'a';
p = p->next[k];
}
if(!p)
return 0;
else
return p->nCount;
}
int main()
{
char s[11];
TrieNode * Root = NULL;
printf("請輸入想儲存的字串:\n");
while(gets(s) && s[0])
{
Insert(&Root, s);
}
printf("請輸入查詢的首碼:\n");
while(gets(s))
{
printf("%d\n", Search(&Root, s));
}
return 0;
}