字典树
2015-08-24 15:45
155 查看
关于字典树的解释请看网址:http://www.java3z.com/cwbwebhome/article/article8/83591.html?id=4750
该网址贴出了java实现一个a-z 26个字母的字典树以及一个案例,一定要看这个案例。
#include<iostream>
#include<string>
using namespace std;
const int size = 26;
class TrieNode{
public:
int num;
//有多少单词通过这个节点,即节点字符出现的次数,也说明了有多少son引用被用到,或者说有多少条被用到的树的边,或者说是该节点的度
TrieNode* son[size];
//所有儿子节点的指针
bool isEnd;
//是不是最后一个节点,即叶子节点
char val;
//节点的值
public:
TrieNode(){
num = 1;
isEnd = false;
// son = new TrieNode[26];
//有待商榷
for(int i = 0; i< size; i++)
son[i] = NULL;
}
};
class Trie{
private:
TrieNode* root;
public:
Trie(){
root = new TrieNode();
root->val = '*';//表示根节点的值
}
//在字典树中插入一个单词
void insert(string& str){
if(str == "" || str.length() == 0)
return;
TrieNode* node = root;
const char* letters = str.c_str();
for(size_t i = 0, len = str.length(); i< len; i++){
int pos = *(letters+i) - 'a';
if(node->son[pos] == NULL){
node->son[pos] = new TrieNode();
node->son[pos]->val = *(letters + i);
}else{
node->son[pos]->num ++;
}
node = node->son[pos];
}
node->isEnd = true;
}
// 计算单词前缀的数量
int countPrefix(string& prefix){
if(prefix == "" || prefix.length() == 0)
return -1;
TrieNode* node = root;
const char* letters = prefix.c_str();
for(size_t i = 0, len = prefix.length(); i< len; i++){
int pos = *(letters + i) - 'a';
if(node->son[pos] == NULL){
return 0;
}else{
node = node->son[pos];
}
}
return node->num;
}
// 在字典树中查找一个完全匹配的单词
bool has(string& str){
if(str == "" || str.length() == 0)
return false;
TrieNode* node = root;
const char* letters = str.c_str();
for(size_t i = 0, len = str.length(); i< len; i++){
int pos = *(letters + i) - 'a';
if(node->son[pos] != NULL)
node = node->son[pos];
else
return false;
}
return node->isEnd;
}
// 前序遍历字典树
void preTraverse(TrieNode* node){
if(node != NULL){
cout << node->val <<"-";
for(int i = 0; i< size; i++){
if(node->son[i] != NULL)
preTraverse(node->son[i]);
}
}
}
TrieNode* getRoot(){
return root;
}
};
int main(){
Trie* tree = new Trie();
string strs[5] = {
"banana",
"band",
"bee",
"absolute",
"acm"
};
string prefix[4]={
"ba",
"b",
"band",
"abc"
};
// for(int i = 0; i< (strs->length()); i++){
// for(int i = 0; i< sizeof(procedureList)/sizeof(string); i++){
for(int i = 0; i< 5; i++){
tree->insert(strs[i]);
}
string pre = "abc";
cout << (tree->has(pre)) << endl;
tree->preTraverse(tree->getRoot());
cout<<endl;
//tree.printAllWords()
// for(int i = 0; i< (prefix->length()); i++){
for(int i = 0; i< 4; i++){
int num = tree->countPrefix(prefix[i]);
cout<< prefix[i] << " " << num << endl;
}
return 0;
}
该网址贴出了java实现一个a-z 26个字母的字典树以及一个案例,一定要看这个案例。
</pre>下面是java代码:</p><p>public class Trie {<span style="white-space:pre"> </span><span style="white-space:pre"> </span>private class TrieNode{<span style="white-space:pre"> </span>//内部类,字典树节点类<span style="white-space:pre"> </span>private int num;<span style="white-space:pre"> </span>//有多少单词通过这个节点,即节点字符出现的次数,也说明了有多少son引用被用到,或者说有多少条被用到的树的边,或者说是该节点的度<span style="white-space:pre"> </span>private TrieNode[] son;<span style="white-space:pre"> </span>//所有儿子节点<span style="white-space:pre"> </span>private boolean isEnd;<span style="white-space:pre"> </span>//是不是最后一个节点<span style="white-space:pre"> </span>private char val;<span style="white-space:pre"> </span>//节点的值<span style="white-space:pre"> </span><span style="white-space:pre"> </span>TrieNode(){<span style="white-space:pre"> </span>num = 1;<span style="white-space:pre"> </span>son = new TrieNode[SIZE];<span style="white-space:pre"> </span>isEnd = false;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>private int SIZE = 26;<span style="white-space:pre"> </span>private TrieNode root;<span style="white-space:pre"> </span>//字典树的根<span style="white-space:pre"> </span><span style="white-space:pre"> </span>Trie(){<span style="white-space:pre"> </span>root = new TrieNode();<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>//在字典树中插入一个单词<span style="white-space:pre"> </span>public void insert(String str){<span style="white-space:pre"> </span><span style="white-space:pre"> </span>if(str == null || str.length() == 0)<span style="white-space:pre"> </span>return;<span style="white-space:pre"> </span><span style="white-space:pre"> </span>TrieNode node = root;<span style="white-space:pre"> </span>char[] letters = str.toCharArray();<span style="white-space:pre"> </span>for(int i = 0, len = str.length(); i< len; i++){<span style="white-space:pre"> </span>int pos = letters[i] - 'a';<span style="white-space:pre"> </span>if(node.son[pos] == null){<span style="white-space:pre"> </span>node.son[pos] = new TrieNode();<span style="white-space:pre"> </span>node.son[pos].val = letters[i];<span style="white-space:pre"> </span>}else{<span style="white-space:pre"> </span>node.son[pos].num++;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>node = node.son[pos];<span style="white-space:pre"> </span>//使node指向儿子节点<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>node.isEnd = true;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>// 计算单词前缀的数量<span style="white-space:pre"> </span>public int countPrefix(String prefix){<span style="white-space:pre"> </span><span style="white-space:pre"> </span>if(prefix == null || prefix.length() == 0)<span style="white-space:pre"> </span>return -1;<span style="white-space:pre"> </span><span style="white-space:pre"> </span>TrieNode node = root;<span style="white-space:pre"> </span>char[] letters = prefix.toCharArray();<span style="white-space:pre"> </span>for(int i = 0, len = prefix.length(); i< len; i++){<span style="white-space:pre"> </span>int pos = letters[i] - 'a';<span style="white-space:pre"> </span>if(node.son[pos] == null){<span style="white-space:pre"> </span>return 0;<span style="white-space:pre"> </span>}else{<span style="white-space:pre"> </span>node = node.son[pos];<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>return node.num;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>// 在字典树中查找一个完全匹配的单词<span style="white-space:pre"> </span>public boolean has(String str){<span style="white-space:pre"> </span><span style="white-space:pre"> </span>if(str == null || str.length() == 0)<span style="white-space:pre"> </span>return false;<span style="white-space:pre"> </span><span style="white-space:pre"> </span>TrieNode node = root;<span style="white-space:pre"> </span>char[] letters = str.toCharArray();<span style="white-space:pre"> </span>for(int i = 0, len = str.length(); i< len; i++){<span style="white-space:pre"> </span>int pos = letters[i] - 'a';<span style="white-space:pre"> </span>if(node.son[pos] != null)<span style="white-space:pre"> </span>node = node.son[pos];<span style="white-space:pre"> </span>else<span style="white-space:pre"> </span>return false;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>return node.isEnd;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>// 前序遍历字典树<span style="white-space:pre"> </span>public void preTraverse(TrieNode node){<span style="white-space:pre"> </span><span style="white-space:pre"> </span>if(node != null){<span style="white-space:pre"> </span>System.out.print(node.val + "-");<span style="white-space:pre"> </span>for(TrieNode child : node.son){<span style="white-space:pre"> </span>preTraverse(child);<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>public TrieNode getRoot() {<span style="white-space:pre"> </span>return root;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>public void setRoot(TrieNode root) {<span style="white-space:pre"> </span>this.root = root;<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>public static void main(String[] args) {<span style="white-space:pre"> </span>Trie tree = new Trie();<span style="white-space:pre"> </span>String[] strs={<span style="white-space:pre"> </span>"banana",<span style="white-space:pre"> </span>"band",<span style="white-space:pre"> </span>"bee",<span style="white-space:pre"> </span>"absolute",<span style="white-space:pre"> </span>"acm"<span style="white-space:pre"> </span>};<span style="white-space:pre"> </span>String[] prefix={<span style="white-space:pre"> </span>"ba",<span style="white-space:pre"> </span>"b",<span style="white-space:pre"> </span>"band",<span style="white-space:pre"> </span>"abc"<span style="white-space:pre"> </span>};<span style="white-space:pre"> </span><span style="white-space:pre"> </span>for(String str : strs){<span style="white-space:pre"> </span>tree.insert(str);<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span><span style="white-space:pre"> </span>System.out.println(tree.has("abc"));<span style="white-space:pre"> </span>tree.preTraverse(tree.getRoot());<span style="white-space:pre"> </span>System.out.println();<span style="white-space:pre"> </span><span style="white-space:pre"> </span>//tree.printAllWords()<span style="white-space:pre"> </span>for(String pre : prefix){<span style="white-space:pre"> </span>int num = tree.countPrefix(pre);<span style="white-space:pre"> </span>System.out.println(pre + " " + num);<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>}}</p><p></p><p>接下来是把该程序该为C++代码:</p><p><pre name="code" class="cpp">
#include<iostream>
#include<string>
using namespace std;
const int size = 26;
class TrieNode{
public:
int num;
//有多少单词通过这个节点,即节点字符出现的次数,也说明了有多少son引用被用到,或者说有多少条被用到的树的边,或者说是该节点的度
TrieNode* son[size];
//所有儿子节点的指针
bool isEnd;
//是不是最后一个节点,即叶子节点
char val;
//节点的值
public:
TrieNode(){
num = 1;
isEnd = false;
// son = new TrieNode[26];
//有待商榷
for(int i = 0; i< size; i++)
son[i] = NULL;
}
};
class Trie{
private:
TrieNode* root;
public:
Trie(){
root = new TrieNode();
root->val = '*';//表示根节点的值
}
//在字典树中插入一个单词
void insert(string& str){
if(str == "" || str.length() == 0)
return;
TrieNode* node = root;
const char* letters = str.c_str();
for(size_t i = 0, len = str.length(); i< len; i++){
int pos = *(letters+i) - 'a';
if(node->son[pos] == NULL){
node->son[pos] = new TrieNode();
node->son[pos]->val = *(letters + i);
}else{
node->son[pos]->num ++;
}
node = node->son[pos];
}
node->isEnd = true;
}
// 计算单词前缀的数量
int countPrefix(string& prefix){
if(prefix == "" || prefix.length() == 0)
return -1;
TrieNode* node = root;
const char* letters = prefix.c_str();
for(size_t i = 0, len = prefix.length(); i< len; i++){
int pos = *(letters + i) - 'a';
if(node->son[pos] == NULL){
return 0;
}else{
node = node->son[pos];
}
}
return node->num;
}
// 在字典树中查找一个完全匹配的单词
bool has(string& str){
if(str == "" || str.length() == 0)
return false;
TrieNode* node = root;
const char* letters = str.c_str();
for(size_t i = 0, len = str.length(); i< len; i++){
int pos = *(letters + i) - 'a';
if(node->son[pos] != NULL)
node = node->son[pos];
else
return false;
}
return node->isEnd;
}
// 前序遍历字典树
void preTraverse(TrieNode* node){
if(node != NULL){
cout << node->val <<"-";
for(int i = 0; i< size; i++){
if(node->son[i] != NULL)
preTraverse(node->son[i]);
}
}
}
TrieNode* getRoot(){
return root;
}
};
int main(){
Trie* tree = new Trie();
string strs[5] = {
"banana",
"band",
"bee",
"absolute",
"acm"
};
string prefix[4]={
"ba",
"b",
"band",
"abc"
};
// for(int i = 0; i< (strs->length()); i++){
// for(int i = 0; i< sizeof(procedureList)/sizeof(string); i++){
for(int i = 0; i< 5; i++){
tree->insert(strs[i]);
}
string pre = "abc";
cout << (tree->has(pre)) << endl;
tree->preTraverse(tree->getRoot());
cout<<endl;
//tree.printAllWords()
// for(int i = 0; i< (prefix->length()); i++){
for(int i = 0; i< 4; i++){
int num = tree->countPrefix(prefix[i]);
cout<< prefix[i] << " " << num << endl;
}
return 0;
}
相关文章推荐
- [rxjs] Shares a single subscription -- publish()
- yum源修改为本地光盘镜像
- SpringMVC+Mysql实例详解
- 杭电3501Calculation 2 欧拉函数
- 谈谈3D打印成本之中的奥秘
- HDOJ 1407 测试你是否和LTC水平一样高
- _stdcall,_cdecl区别
- POJ 3281( 网络流 最大流 ISAP)
- resize函数
- c++ 设计模式之 策略模式与工厂模式结合
- 黑马程序员_Collection集合之Set
- STL学习----入门(1)[functional]
- 一起做RGB-D SLAM(7) (完结篇)
- IOS生成UUID
- java面试笔记
- 热门话题自动换行自定义控件
- window服务器 合并分区
- 降低3D打印成本的几种方法
- 内存溢出之Tomcat内存配置
- 编译vim以支持lua