决策树cart算法python实现,用cart算法画决策树例题
特别声明
本文仅为笔记文章,不存在抄袭。
以下是我在研究过程中参考的链接。有很多。以下是我记得的事情。
1.字典树的概念
字典树也叫词搜索树,因为它的搜索速度快,所以用在词搜索系统中。树的数据结构。之所以快,是因为用的是空间而不是速度。
2.字典树的特征:
字典树有三个基本属性。
1.根节点不包含字符,除了根节点之外的每个节点只包含一个字符。
2.从根节点到某个节点,节点对应的字符串由路径上的文本连接。
3.每个节点的所有子节点都包含不同的字符。
3.下图显示了包含以下字符串的字典树结构。
addadbc
再见
Tree.png
4.字典树应用场景
1)、快速搜索字符串
给出由n个单词组成的成语和用小写英文写的冠词。请以最快的顺序写出成语中没有的单词。
在这个问题上,通过枚举数组、使用哈希、使用字典树等方式在树上构建短语是非常高效的。然后看文章对比。
2)字典树在“字符串”排序中的应用
给定只由一个单词组成的n个互不相同的英文名,按照字典顺序从小到大输出。
按字典树排序,按数组创建字典树。这棵树中每个节点的所有子节点。
很明显是按字母顺序排的。先扫描一下树。
3)字典树在最长公共前缀问题中的应用。
为所有字符串创建一棵字典树,对于两个字符串的最长公共前缀的长度,即它们所属节点的公共祖先的个数,将问题转化为最近公共祖先问题。
5.字典树的数据结构
从上面的描述可以看出,字典树的数据结构如下。
类TrieNode {
char c;
进入会计;
映射标题;
}
上述属性的描述:
1,C,存储这个节点的数据,只有一个字符。(注意只有一个字)。
2.occurrence应该从这个词的意思知道它的意思是出现的频率。Occurances是对应于当前节点的字符串在字典树中出现的次数。
3.children是当前节点的子节点,用于保存下一个节点的字符。
7.根据字符串的常用功能,字典树类应该实现的特性。
1)查询是否包含字符串。
2)询问字符串出现的频率。
3)插入一个字符串
4)删除字符串
5)获取字典树的整体规模,即字典树中包含的不同字符串的数量。
基于以上考虑,Trie类可以构建一个只需要实现这个接口的接口。
根据8.6中描述的特征创建抽象类。
通用abt rie {
//确定字典树中是否存在该字符串。
publicabstractbooleancontains(字符串字);
//返回该字符串在字典树中出现的次数。
常见跟踪要求(字符串字);
//插入一个字符串。
一个公共字符串(字符串字);
//删除字符串。
后台文件(字符串字);
//整个字典树中不同字符串的数量,即存储的不同字符串的数量。
公共抽象int size(;
}
每个抽象方法的描述已经详细描述过了,这里不再赘述。
9.界面中每种方法的实现原理如下
1)插入一个字符串
1.从头到尾遍历字符串中的所有字符。
2.从根节点插入。如果这个字符存在,就不需要插入新的节点。如果它不存在,请插入一个新节点。
3.然后,按照上述方法继续沿着插入的节点插入剩余的节点。
4.若要计算每个字符串的出现次数,请在最后一个节点中插入occurrences,表示该字符串的出现次数增加了一倍。
2)删除字符串
1.从根节点的子节点开始,每个字符串的第一个字符必须位于根节点的子节点,所以判断其当前节点是否为空。如果它没有到达要删除的字符串的最后一个字符,则该字符串不存在。如果到达了叶子的节点,但是没有遍历整个字符串,则整个字符串不存在。例如,在“哈兰1994”中,“哈兰”将被删除。
2.如果找到要删除的字符串,只需要在最后一个字符是叶节点的情况下删除即可。此外,删除操作仅发生在叶节点上。比如删除“byebye”,但是字典里有“byebyeha”,就是拜拜的意思。
不需要删除它,只需更改occurrences=0来指示字符串 byebye 不再存在于字典中。
3.当最后一个字符被遍历时,这意味着它存在于字典中,当前节点的occurances必须被设置为0,这表明由当前节点表示的字符串不再存在。是否删除,需要考虑2中提到的情况,即只删除只发生在叶子节点上。
3)获取字符串出现的次数
1.当我们设计数据结构时,我们有一个occurances属性。
2.判断字符串是否存在,如果存在,返回相应字符下的occurances。
4)有没有字符串?
1.查询字符串从第一个字符开始。
2.当查询的位置已经超过了字符串的长度,比如“adc”,但是我们发现树的深度已经超过了C,它肯定是不存在的。
3.如果查询的位置正好是字符串的长度,那么就可以判断当前节点的合格子节点是否存在。如果是,则字符串存在,否则不存在。
4.在其他情况下,需要进一步询问。如果存在符合要求的子节点,则继续查询;否则,它们就不存在。
5)整个Trie树的大小,即不同字符串的数量
1.只需返回Trie数据结构中的size属性。
2.大小属性将在插入和移除操作后更新。
10.代码实现
1)插入一个字符串
int insert(String s,int pos) {
//如果插入空字符串,将直接返回
//此方法从pos=0开始递归调用,其中pos是指插入的pos字符。
if (s==null pos=s.length())
返回0;
//如果当前节点没有子节点,则返回新节点
if (children==null)
children=new HashMap();
//创建一个TrieNode
char c=s . charat(pos);
TrieNode n=children . get(c);
//确保字符保存在要插入的节点中。
if (n==null) {
n=新的TrieNode(c);
children.put(c,n);
}
//在插入结束时,直到插入最后一个字符,返回的结果是字符串出现的次数。
//否则,继续插入下一个字符
if (pos==s.length() - 1) {
n .出现次数;
返回n.occurances
}否则{
返回n.insert(s,位置1);
}
}
2)删除字符串
boolean remove(String s,int pos) {
if (children==null s==null)
返回false
//取出pos字符,如果不存在,返回false
char c=s . charat(pos);
TrieNode n=children . get(c);
if (n==null)
返回false
//递归exit是字符串的最后一个字符,show ga occurrences=0,表示已经被删除。
//否则,继续递归到最后一个字符
布尔ret
if (pos==s.length() - 1) {
int before=n.occurances
n . occurrences=0;
ret=之前;
}否则{
ret=n.remove(s,位置1);
}
//1.如果我们想去掉“你好”,但有一个“你好”,你不要
//需要删除保存的字符,因为它的出现已经被
//已解决
//0 witch表示字符串s不再存在。
//2 .其出现次数必须为0,例如,
//当你想删除 harlan1994 ,但是没有这样的序列,
//只有‘哈兰’
//所以当我们到达最后一个char n 时,pos!=s.length() - 1,其
//出现次数不能是
//定为0,而它为0,所以它不是需要的序列
//已删除。
//如果我们只是去掉一片叶子,向上修剪。
//删除后,必须删除不必要的字符。
//比如删除了保存的“Harlan”,那么如果在叶子节点中保存了n,就说明虽然标记为不存在,但还是占用了空间。
//所以不得不删除,但是如果删除了“Harlan”,但是这个“Harlan1994”还存储在Trie中,那么就不需要长时间删除字符了。
if(n . children==null n . occurrences==0){
children . remove(n . c);
if (children.size()==0)
children=null
}
返回ret
}
3)找出一个字符串出现的次数
TrieNode lookup(String s,int pos) {
if (s==null)
返回空
//如果找的次数已经超过了字符的长度,说明,已经递归到超过字符串的深度了,表明字符串不存在
if(pos=s . length() children==null)
返回空
//如果刚好到了字符串最后一个,则只需要返回最后一个字符对应的结点,若节点为空,则表明不存在该字符串
else if (pos==s.length() - 1)
还孩子。get(s . charat(pos));
//否则继续递归查询下去,直到没有孩子节点了
否则{
TrieNode n=子节点。get(s . charat(pos));
return n==null?null : n.lookup(s,pos 1);
}
}
以上库库普方法返回值是一个特里节点,要找某个字符串出现的次数,只需要看其中的出现次数即可。
要看是否包含某个字符串,只需要看是否为空节点即可。
11、下面来一个应用,题目如下:
不考虑字母大小写,在一篇文章中只有英文,不包含其余任何字符,求这篇文章中不同单词的个数。
并求所给单词的出现次数。
1)建立一个测试类样本,添加两个方法分别求以上两个问题
2)添加一个求取文件内容,并添加字符串到字典树中的方法,关键代码如下:
.
私有void init() {
尝试{
输入流=新文件输入流(新文件(
e:\ \ Eclipse \ \ trie \ \ src \ \ com \ \ Harlan \ \ trie \ \ bible。txt’);
addToDictionary(in);
} catch(异常e) {
e。printstacktrace();
}
}
公共void addToDictionary(输入流f)抛出IOException,
文件未找到异常{
长t=系统。当前时间毫秒();
最终int bufSize=1000
int读取
int numWords=0;
InputStreamReader fr=null
尝试{
fr=new InputStreamReader(f);
char[]buf=new char[bufSize];
while ((read=fr.read(buf))!=-1) {
//TODO修改此拆分正则表达式,使其真正有用
字符串[]单词=新字符串(buf,0,read).split( \ \ W );
for (String s : words) {
mTrie.insert
数字
}
}
}最后{
如果(fr!=null) {
尝试{
法郎close();
} catch (IOException e) {
}
}
}
System.out.println(从文件读取并插入数字
单词到trie in’(系统。当前时间(毫秒()-t)
/1000.0 秒);
}
public int getSize() {
如果(mTrie!=null) {
返回里山。size();
}
返回0;
}
public int getCount(String s) {
返回移动频率;
}
测试结果截图如下:
测试。png
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。