字典樹-單詞查找樹,Trie樹

1、

哈希樹的變種。典型應用是用於統計,排序和保存大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。它的優點是:利用字符串的公共前綴來減少查詢時間,最大限度地減少無謂的字符串比較,查詢效率比哈希樹高。

根節點不包含字符,除根節點外每一個節點都只包含一個字符; 從根節點到某一節點,路徑上經過的字符連接起來,爲該節點對應的字符串; 每個節點的所有子節點包含的字符都不相同。

 

如果將指針變量指向一個已開闢過的,即已有的空間,就不需要重新開闢內存空間了,只有需要開闢的時候纔開闢內存空間

https://blog.csdn.net/faihung/article/details/90648217    int *q;只有地址,沒有內存空間。這個地址是隨機地址。

像下面這種分配好的就不用new

 ///////////////////////////////int *p 只能指向別人的內存不能在棧上自動分配了(*p=1是錯的)

 

class Solution {
public:
    class Tree{
    public:
        bool word_here=false;
        Tree* v[26]={nullptr};
        static void insert(Tree* t, const string &s){
            for(char c:s){
                if(!t->v[c-'a'])//t->v[c - 'a'] == nullptr
                    t->v[c-'a'] = new Tree();//一開始都是空的都要分配空間
                t = t->v[c-'a'];
            }
            t->word_here = true;
        }
        static bool search(Tree* t, const string &s){
            for(char c:s){
                if(!t->v[c-'a']->word_here)//查找c失敗 false  這裏判斷之前的前綴是不是單獨的一個字符串
                    return false;
                t = t->v[c-'a'];
            }
            return true;
        }
    };
    string longestWord(vector<string>& words) {
        Tree* root = new Tree();
        for(string &s:words)
            Tree::insert(root, s);//插入
        string longest;
        for(string &s:words)
            if(Tree::search(root, s)){
                if(s.size()>longest.size())
                    longest=s;
                else if(s.size()==longest.size()&&s<longest)////這裏最後比較大小
                    longest=s;
            }
        return longest;
    }
};


 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////參考/////////////////////////////////////////////////////////

#include<cstdio>
#include<cstdlib>
using namespace std;
char s[11];
struct Trie{
    Trie* next[26];          //結構體指針 有26種字符
    int sum;                //單詞出現的次數
    Trie(){                    //構造函數 便於初始化
        for(int i=0;i<26;i++){             //初始化
            next[i]=NULL;        //初始時,每個字符所對應數組下標中的指針爲空
        }
        sum=0;
    }
}root;
void insert(char* s)   //創建字典樹 在字典樹上插入結點
{
    Trie* p=&root;            //從根結點開始遍歷
    for(int i=0;s[i];i++){         //遍歷單詞的每一個字符
        if(p->next[s[i]-'a']==NULL){   //判斷字符所對應結構體指針數組下標中的指針是否爲空
            p->next[s[i]-'a']=new Trie;  //如果爲空 就新建一個結點 
        }
        p=p->next[s[i]-'a'];   //將指針指向當前字符所對應的結構體指針數組的下標所對應的地址
        p->sum++;
    }
}
int find(char* s)        //查找單詞
{
    Trie* p=&root;       //從根結點開始遍歷
    for(int i=0;s[i];i++){      //遍歷單詞的每一個字符
        if(p->next[s[i]-'a']==NULL)return 0;   // 如果下標所對應的指針爲空 查找失敗
        else p=p->next[s[i]-'a'];   //如果不爲空 遍歷下一個字符 直至遍歷結束
    }
    return p->sum;   //返回遍歷完的最後一個結點中所對應的數據 代表當前當前單詞出現的次數
}
int main(){
    while(gets(s)&&s[0]!='\0')             //讀取字典中的單詞 將其插入字典樹中
        insert(s);
    while(scanf("%s",s)==1){           //在字典樹中查找單詞出現的次數
        printf("%d\n",find(s));
    }
    return 0;
}

 

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