1. 程式人生 > 實用技巧 >字典樹(tried)字首樹

字典樹(tried)字首樹

字典樹又稱為字首樹,是一種用來統計字串字首數目的資料結構,字典樹的實現相對於線段樹等資料結構還是比較簡單。

字典樹的有3個核心函式,insert , search ,delete。

實現字典樹常用的方式有倆種,一個是結構體+指標,還用一種是二維陣列模擬,思想都是一樣的。

1、首先定義字典樹的節點:

class node{
public:
    int path;
    int end;
    node *mp[26];
    node (){
        path=end=0;
        for (int i=0;i<26;i++) 
            mp[i]=NULL;
    }
};

節點中的path用來記錄該節點被幾個字串用過。end用來記錄以該節點結尾的字串的個數。node *mp[26]是一個指標陣列,我們可以用該陣列記錄該節點指向的下一個節點,陣列大小為26指的是從a~z 26個英文字母,這個可以根據自己的尋求更改。比如說 x->mp[i]指的是節點x指向下一個值為i的節點。

2、節點的插入。

node *root = new node();
void insert(string s){
    node *now=root;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'
a'; if(root->mp[id]==NULL){ root->mp[id]=new node(); } root=root->mp[id]; root->path++; } root->end++; root=now; }

首先定義一個根節點指標。然後遍歷字串S的每一個字元,root->mp[id]!=NULL,說明遍歷到目前為止,字首字串曾經出現過,即我們之前儲存過的字串和該字串有共同的字首。 如果root->mp[id]==NULL,說明該字首第一次出現,要新申請一個節點用來儲存當前字元,並作為上一個節點的兒子節點。

root->path++; path記錄的是該節點被幾個字串用過。沒用一次+1就可以了。插入完之後 root->end++; 說明該節點為當前字串的終止節點。

3、字串的查詢

int search(string s){
    node *now=root;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'a';
        if(now->mp[id]!=NULL){
            now=now->mp[id];
        }
        else return 0;//不存在. 
    }
    return now->path;
}

查詢儲存過的字串無非就是根據字串s,從root出發能不能找到一條路徑。如果找著找著沒路了,即S沒有遍歷完遇到了NULL,那就沒找到嘍,否則返回path,意思的有樹中喲普幾個以該字串為字首的字串。

4、字串的刪除

void de(string s){
    node *now=root;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'a'; 
        root->mp[id]->path--;
        if(root->mp[id]->path==0){
            root->mp[id]=NULL;
            return ;
        }
        root=root->mp[id];
    }
    root->end--;
    root=now;
}

如果我們想要刪除之前儲存過的字串,只需要修改每個節點的path,如果說該節點的path為0了,直接將指標指為空即可並退出,如果沒有遇到path=0的情況,在最後節點的end--,說明以該節點為結尾的字串減一。

class node{
public:
    int path;
    int end;
    node *mp[26];
    node (){
        path=end=0;
        for (int i=0;i<26;i++) 
            mp[i]=NULL;
    }
};
node *root = new node();
void insert(string s){
    node *now=root;
    if(root==NULL) return ;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'a';
        if(root->mp[id]==NULL){
            root->mp[id]=new node();
        }
        root=root->mp[id];
        root->path++;
    }
    root->end++;
    root=now;
}
int search(string s){
    node *now=root;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'a';
        if(now->mp[id]!=NULL){
            now=now->mp[id];
        }
        else return 0;//不存在. 
    }
    return now->path;
}
void de(string s){
    node *now=root;
    int n=s.size();
    for(int i=0;i<n;i++){
        int id=s[i]-'a'; 
        root->mp[id]->path--;
        if(root->mp[id]->path==0){
            root->mp[id]=NULL;
            return ;
        }
        root=root->mp[id];
    }
    root->end--;
    root=now;
}


        root->path++;