字典树---->Trie树

      字典树(Trie树):顾名思义是一种树形结构,属于哈希树的一种。应用于统计、排序、查找单词统计单词出现的频率等。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

      字典树的结构特点:根节点不代表任何字符。其他节点从当前节点回溯到根节点可以得到它代表的字符串。当然可以再节点上加一个记录该节点所代表单词的属性。字典树的形状如图:

               

        字典树节点的结构:

       节点包含26个指针,每个指针代表一个英文字符节点。26个英文字母那就需要26个指针。节点其他的属性可根据需要添加。一般包含一个记录该节点所代表字符出现次数的属性。

 一种节点定义形式如下:

#define max 26
struct TrieNode
{
   int count;//单词出现的次数
   char* word;//节点表示那个单词
   TrieNode* next[max];//指向26个字符节点的指针。
   TrieNode():count(0),word(0)
   {
	   for(int i=0;i<max;i++)
		   next[i]=NULL;
   }
};

在TrieNode除了26个指针外还有一个记录当前节点所代表单词的属性,和一个记录该单词出现次数的属性。

       字典树一般有插入和查找两个操作,很少用到删除某个节点的操作。

字典树实现代码:

class TrieTree
{
public:
    TrieTree(void)
    {
        pRoot=new TrieNode();
    }
    ~TrieTree(void)
    {
        ReleaseTrie(pRoot);
    }
    TrieTree& Insert(const char* s)
    {
        TrieInsert(pRoot,s);
        return *this;
    }
    int Search(const char* s,int& count)
    {
        return TrieSearch(pRoot,s,count);
        
    }
    void PrintWordNum()
    {
        WordNum(pRoot);
    }
private:
    //插入一个新的单词
    void TrieInsert(TrieNode* root,const char* s);
    //查找某个单词是否存在
    int TrieSearch(TrieNode* root,const char* s,int& count);
    //释放字典树
    void ReleaseTrie(TrieNode* root);
    void WordNum(TrieNode* root);
private:
    TrieNode* pRoot;
};

插入一个单词的代码:

      现在是对单词的统计,所以仅对构成单词的节点,计数加1,当一个节点不为空,但计数为0,是仅代表它是某个单词的前缀。

void TrieTree::TrieInsert(TrieNode* root,const char* s)
{
    if(s==NULL)
        return ;
    TrieNode* p=root;
    int i=0;
    while(s[i]!=0)
    {
        int index=tolower(s[i])-'a';
        if(index<0||index>max)
            return ;
        if(p->next[index]==NULL)
        {
            TrieNode* newNode=new TrieNode();
            p->next[index]=newNode;
        }
        p=p->next[index];
        i++;
    }
    p->word=new char[strlen(s)+1];
    strcpy(p->word,s);
    p->count+=1;
}


查找一个单词出现次数的代码:

返回1表示查找成功,count获得单词出现次数。

int TrieTree::TrieSearch(TrieNode* root,const char* s,int& count)
{
    if(s==NULL||root==NULL)
        return 0;
    TrieNode* p=root;
    int i=0;
    while(s[i]!=0&&p!=NULL)
    {
        int index=tolower(s[i])-'a';
        if(index<0||index>max)
            return 0;
        p=p->next[index];
        i++;
    }
    if(s[i]==0&&p&&p->count!=0)
    {
        count=p->count;
        return 1;
    }
    else
    {
        count=0;
        return 0;
    }

}



释放字典树空间的代码:

void TrieTree::ReleaseTrie(TrieNode* root)
{
    if(root==NULL)
        return ;
    for(int i=0;i<max;i++)
        ReleaseTrie(root->next[i]);
    if(root->word)
        delete root->word;
    delete root;
}


     在对大量的单词使用Insert插入构建好字典树后,遍历整个树,就能的到单词出现的次数了。

void TrieTree::WordNum(TrieNode* root)
{
	if(root==NULL)
		return ;
	if(root->word!=NULL)
	{
		cout<<root->word<<" :"<<root->count<<endl;
	}
	for(int i=0;i<max;i++)
		WordNum(root->next[i]);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值