Trie樹(字典樹) 個人模版

Trie樹的基本實現

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

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

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

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

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

這裏採用第一種,速度較快,適合ACM競賽。

孩子數組大小自定義,此處默認爲字母數26;

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>


using namespace std;


typedef struct Trie
{
    int nCount; //該節點前綴 出現的次數
    struct Trie *next[26]; //孩子結點
}Trie;

Trie Memory[1000000]; //先分配內存 malloc費時間
int allocp = 0;

//初始化節點。nCount計數爲1,next都是爲NULL
Trie * InitNode()
{
    Trie * tmp = &Memory[allocp++];
    tmp->nCount = 1;
    for(int i=0;i<26;i++)
        tmp->next[i]=NULL;
    return tmp;
}
void insertTrie(Trie * * pRoot, char * str)
{
    Trie * tmp = *pRoot;
    int i=0,k;
    //逐個插入
    while(str[i])
    {
        k=str[i]-'a';
        if(tmp->next[k])
        {
            tmp->next[k]->nCount++;
        }else
        {
            tmp->next[k]=InitNode();
        }
        tmp = tmp->next[k];
        i++;
    }
}
int searchTrie(Trie *root,char *str)
{
    if(root==NULL)
        return 0;
    Trie *tmp = root;
    int i=0,k;
    while(str[i])
    {
        k=str[i]-'a';
        if(tmp->next[k])
        {
            tmp = tmp->next[k];
        }else
        {
            return 0;
        }
        i++;
    }
    return tmp->nCount; //返回最後那個結點保存的ncount
}
int main()
{
    int m,n;
    char s[11];
    Trie * root = InitNode();
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s",s);
        insertTrie(&root,s);
    }
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%s",s);
        printf("%d\n",searchTrie(root,s));
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章