字典树
转载请注明出处,谢谢。http://www.cnblogs.com/acmer-roney/---by Roney
【本文摘自百度文库】
综述
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。
性质
它有3个基本性质:
根节点不包含字符,除根节点外每一个节点都只包含一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
每个节点的所有子节点包含的字符都不相同。
假设有abc,abcd,abd, b, bcd,efg,hii这7个单词,可构建字典树如下:
查找一个字符串时,我们只需从根结点按字符串中字符出现顺序依次往下走。如果到最后字符串结束时,对应的结点标记为红色,则该字符串存在;否则不存在。
插入时也只需从根结点往下遍历,碰到已存在的字符结点就往下遍历,否则,建立新结点;最后标记最后一个字符的结点为红色即可。
基本操作
其基本操作有:查找 插入和删除
实现方法
搜索字典项目的方法为:
(1) 从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
(4) 迭代过程……
(5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。
其他操作类似处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 const int kind=26;//字母种类 6 7 struct Treenode//树的结点结构 8 { 9 char ch; //节点处的字符 10 bool isColored; //是否标记为红色 11 int count; //子节点个数 12 Treenode *next[kind];//指向子结点 13 Treenode *parent; //父节点 14 Treenode(char thech, Treenode* par)//结点初始化 15 { 16 ch=thech; 17 isColored=false; 18 count=0; 19 parent=par; 20 for(int i=0;i<kind;i++) 21 next[i]=NULL; 22 } 23 }; 24 25 void insert(Treenode *&root,char *word) //向以root为根结点的树中插入串word 26 { 27 Treenode *location=root; 28 int i=0,branch=0; 29 30 if(location==NULL) { 31 location=new Treenode(' ', NULL); //根节点字符为空,用空格(' ')表示 32 root=location; 33 } 34 35 while(word[i]) 36 { 37 branch=word[i]-'a'; 38 if(!location->next[branch]) 39 location->next[branch]=new Treenode(word[i], location);//如果不存在,建新结点 40 location->count++; 41 location=location->next[branch]; 42 i++; 43 } 44 location->isColored = true; //标记节点为叶节点 45 } 46 47 Treenode* search(Treenode *root,const char *word)//查找,找到则返回相应节点指针 48 { 49 Treenode *location=root; 50 int i=0,branch=0; 51 52 if(location==NULL) return NULL; 53 54 while(word[i]){ 55 branch=word[i]-'a'; 56 if(!location->next[branch]) return NULL; 57 location=location->next[branch]; 58 i++; 59 } 60 if(location->isColored) return location; 61 return NULL; 62 } 63 64 char* longest_prefix(Treenode *root, const char *word) //返回word的最长前缀 65 { 66 Treenode *location=root; 67 int i=0,branch=0; 68 69 if(location==NULL) return NULL; 70 71 while(word[i]) 72 { 73 branch=word[i]-'a'; 74 if(!location->next[branch]) break; 75 location=location->next[branch]; 76 i++; 77 } 78 if(i == 0) return NULL; 79 string str1 = string(word).substr(0, i); 80 char *str = new char[str1.length()+1]; 81 strcpy(str,(char*)str1.c_str()); 82 return str; 83 84 } 85 86 //获取所有以root为根的(红色)结点,并存放到allElement中 87 vector<char*> getAll(Treenode *root, char *str, int i, vector<char*> &allElement) 88 { 89 str[i] = root->ch; 90 91 if(root->isColored) 92 { 93 str[i+1] = '\0'; 94 char *temp = (char*)malloc(strlen(str)*sizeof(char)); 95 strcpy(temp, str+1); 96 temp[strlen(str)-1]='\0'; 97 allElement.push_back(temp); 98 } 99 100 for(int j=0;j<kind;j++) 101 { 102 if(root->next[j]!=NULL) 103 { 104 getAll(root->next[j],str,i+1, allElement); 105 } 106 } 107 return allElement; 108 } 109 110 //获取所有以word为前缀的红色结点,并存放到allElement中(不包含前缀,使用时需额外添加) 111 void autocomplete(Treenode *root, const char *word, char *str, int i, vector<char*> &allElement) 112 { 113 Treenode *location=root; 114 int j=0,branch=0; 115 116 if(location==NULL) return ; 117 118 while(word[j]) 119 { 120 branch=word[j]-'a'; 121 if(!location->next[branch]) return ; 122 location=location->next[branch]; 123 j++; 124 } 125 getAll(location, str, i, allElement); 126 } 127 128 void remove(Treenode *root, const char *word) 129 { 130 Treenode *target = search(root, word); 131 if(!target) return ; 132 if(target->isColored) 133 target->isColored = false; 134 if(target->count == 0) { //如果target没有子节点,则将其从父节点中移除。(不做此步亦可) 135 target->parent->next[target->ch - 'a'] = NULL; 136 } 137 } 138 139 void print(Treenode *root, char *str, int i) //输出所有(红色)节点 140 { 141 str[i] = root->ch; 142 143 if(root->isColored) 144 { 145 str[i+1] = '\0'; 146 puts(str+1); 147 } 148 149 for(int j=0;j<kind;j++) 150 { 151 if(root->next[j]!=NULL) 152 { 153 print(root->next[j],str,i+1); 154 } 155 } 156 } 157 158 159 160 int main() 161 { 162 char word[10]; 163 char ask[10]; 164 char str[20]; 165 Treenode *root=NULL; 166 cout<<"input the strings to build the tire:\n"; 167 while(gets(word)) 168 { 169 if(word[0]=='\0') break; 170 insert(root,word); 171 } 172 173 vector<char*> allElement; 174 vector<char*>::iterator pos; 175 getAll(root, str, 0, allElement); 176 for(pos = allElement.begin(); pos != allElement.end(); ++pos) { 177 cout<<"ab"<<*pos<<endl; 178 } 179 allElement.clear(); 180 cout<<"所有以ab为前缀的红色结点:\n"; 181 autocomplete(root, "ab", str, 0, allElement); 182 for(pos = allElement.begin(); pos != allElement.end(); ++pos) { 183 cout<<"ab"<<*pos<<endl; 184 } 185 //print(root, str, 0); 186 cout<<"abcd的最长前缀: "; 187 cout<<longest_prefix(root, "abcd")<<endl; 188 cout<<"input a string to search: "; 189 gets(ask); 190 search(root,ask) == NULL ? cout<<ask<<" is not found."<<endl : cout<<ask<<" is found."<<endl; 191 remove(root,ask); 192 cout<<"after delete "<<ask<<endl; 193 print(root, str, 0); 194 return 0; 195 }
posted on 2012-09-11 15:37 Acmer_Roney 阅读(199) 评论(0) 编辑 收藏 举报