Trie树

1.概述

          在计算机科学中,trie,又称前缀树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。如图所示:

Trie树_第1张图片

2.Trie的应用

第一:词频统计。

           可能有人要说了,词频统计简单啊,一个hash或者一个堆就可以打完收工,但问题来了,如果内存有限呢?还能这么玩吗?所以这里我们就可以用trie树来压缩下空间,因为公共前缀都是用一个节点保存的。

第二: 前缀匹配

            就拿上面的图来说吧,如果我想获取所有以"a"开头的字符串,从图中可以很明显的看到是:aa,aba,abba等,如果不用trie树, 你该怎么做呢?很显然朴素的做法时间复杂度为O(N2) ,那么用Trie树就不一样了,它可以做到h,h为你检索单词的长度, 可以说这是秒杀的效果。

3.源码实现

            代码主要实现【以boy为例,insert执行步骤 由根节点开始

                1.location.data=null; 计算'b'-'a'=1; location.branch[1]=new trie_node;

                2.设置location=location->branch[1];循环执行步骤1;

                3.待将boy末尾,将location.data=PRON;此时boy插入完毕。

/*
* Copyright (C) BurNing
*/

#include<iostream>
#include<string.h>
using namespace std;
const int num_chars = 26;
struct Trie_node {
  char* data;
  Trie_node* branch[num_chars];
  Trie_node();
};

class Trie
{
public:
  Trie();
  Trie(Trie& tr);
  //virtual ~Trie();
  int trie_search(const char* word, char* entry ) const;
  int insert(const char* word, const char* entry);
protected:
  struct Trie_node {
    char* data;
    Trie_node* branch[num_chars];
    Trie_node();
  };
  Trie_node* root;
};

Trie::Trie_node::Trie_node()
{
  data = NULL;
  for (int i=0; i<num_chars; ++i) branch[i] = NULL;
}

Trie::Trie():root(NULL) {}

int Trie::trie_search(const char* word, char* entry ) const
{
  int position = 0;
  char char_code;
  Trie_node *location = root;
  while ( location!=NULL && *word!=0 ) {
    if ( *word>='A' && *word<='Z' )
      char_code = *word-'A';
    else if ( *word>='a' && *word<='z' )
      char_code = *word-'a';
    else
      return 0;
    location = location->branch[char_code];
    position++;
    word++;
  }
  if ( location != NULL && location->data != NULL ) {
    strcpy(entry,location->data);
    return 1;
  } else return 0;
}

int Trie::insert(const char* word, const char* entry)
{
  int result = 1, position = 0;
  if ( root == NULL ) root = new Trie_node;
  char char_code;
  Trie_node *location = root;
  while ( location!=NULL && *word!=0 ) {
    if ( *word>='A' && *word<='Z' )
      char_code = *word-'A';
    else if ( *word>='a' && *word<='z' )
      char_code = *word-'a';
    else
      return 0;
    if ( location->branch[char_code] == NULL )
      location->branch[char_code] = new Trie_node;
    location = location->branch[char_code];
    position++;
    word++;
  }
  if (location->data != NULL)
    result = 0;
  else {
    location->data = new char[strlen(entry)+1];
    strcpy(location->data, entry);
  }
  return result;
}

int main()
{
  Trie t;
  char entry[100];
  t.insert("a", "DET");
  t.insert("abacus","NOUN");
  t.insert("abalone","NOUN");
  t.insert("abandon","VERB");
  t.insert("abandoned","ADJ");
  t.insert("abashed","ADJ");
  t.insert("abate","VERB");
  t.insert("this", "PRON");
  if (t.trie_search("this", entry))
    cout<<"'this' was found. pos: "<<entry<<endl;
  if (t.trie_search("abate", entry))
    cout<<"'abate' is found. pos: "<<entry<<endl;
  if (t.trie_search("baby", entry))
    cout<<"'baby' is found. pos: "<<entry<<endl;
  else
    cout<<"'baby' does not exist at all!"<<endl;
}

你可能感兴趣的:(Trie树)