认识trie

java.lang.RuntimeException: Exceed max trie node in key chunk, increase reduce number to resolve the problem.(If you use the LOCAL mode, please convert it to CLUSTER mode.)
        io.transwarp.inceptor.util.TrieChunks.appendTrieNode_raw(RadixTrie.java:231)
        io.transwarp.inceptor.util.RadixTrie.findCompressedChildAndPutKey(RadixTrie.java:782)
        io.transwarp.inceptor.util.RadixTrie.putKey(RadixTrie.java:911)
        io.transwarp.inceptor.util.RadixTrie.putKey(RadixTrie.java:857)
        io.transwarp.inceptor.util.RadixTrie.putAndOverwriteKey(RadixTrie.java:1105)

总结 MR Job的几种运行模式  :

  1.在服务器上运行yarn集群模式:

      在Eclipse中开发好mr程序(在Windows或Linux中都可),然后打包成jar包,上传到服务器。

        执行命令 hadoop jar jar包名   Runner类的全类名


  2.在Linux中Eclipse开发平台中直接启动Runner类运行main方法,这种方式既可以为yarn集群模式,也可以为本地模式:

     关键点是:

       取决于一个配置参数:mapreduce.framework.name=local(yarn) 

       当为local时则运行为本地模式;当为yarn时则为运行yarn集群模式。

 ----yarn模式:

      a.将mr工程导出为jar包,放在工程目录下。

      b.在main方法中,加入一个配置参数,conf.set("mapreduce.job.jar","mr导出的jar包名")


----本地模式:

     在Eclipse中将mr工程导出为jar包,拷贝到当前目录下,直接运行main方法。

 3.在Windows的Eclipse中运行本地模式的步骤:

     a.在Windows中存放hadoop的安装包,并配置其环境变量。

     b.根据Windows的版本,对应的替换掉hadoop安装包中的本地库(bin、lib)         

     c.mr工程中不需要设置mapreduce.framework.name。

 4.在Windows的Eclipse中运行yarn集群模式的步骤:

   此时只添加该单一的参数,设置conf.set("mapreduce.job.jar","mr导出的jar包名")是不行的,因为在Windows中还需要其他的系统变量如:JAVA_HOME 等。因为在将job提交到服务器Linux中会有不兼容的问题出现,比如环境变量%与Linux中的$的区别。此时我们可以修改yarn-Runner方法的源码。此处修改较多。不建议使用。


1 Trie简介

       Trie树,又称单词查找树键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

        在本文中,对于输入的进行序列化,比如输入“单词查找树”,序列化为“单/词/查/找/树”,这样可以进行任何一种自定义的数据插入和查询。序列化输入可以根据自己的需要进行相应的改动,这样可以把Trie树结构应用到很多其他的语言和领域。

        本Trie树结构的优点在于

       1 不限制子节点的数量;

       2 自定义的输入序列化,突破了具体语言、应用的限制,成为一个通用的框架;

       3 可以进行最大Tokens序列长度的限制;

       4 根据已定阈值输出重复的字符串;

       5 提供单个字符串频度查找功能;

       6 速度快,在两分钟内完成1998年1月份人民日报(19056行)的重复字符串抽取工作。

2 结构示意图

3  实现代码

我自己用java实现了一个最基本的Trie树,功能有:插入单词,查找单词,删除单词,以字典序遍历打印出所有出现过的单词及频数。另有几点说明如下:

  • 每 个结点存储子结点时不使用固定长度的数组,而使用Map<Character, TrieNode>结构,这样可以处理任意字符集。当然,你还得准备一个char型数组,以字典序存储要处理的所有字符,遍历的时候回用到。顺便提 一下,如果你确定处理的只涉及26个英文字母,用一个26个大小的数组来存储子结点是个不错的选择,且比较简单。
  • Node结点中存 储哪些值要看实际情况,在本例中存储的是单词的出现次数。你也可以增加一个字段prefixNum,用于存储当前前缀出现次数(即含有当前前缀的单词 数)。这个参数是很有用的,而且在删除操作时,只需要从根结点往下判断第一个prefixNum==1的删除即可。自己试一下就明白了。我之所以没采用, 主要想练习一下递归算法,好久没用了。 Trie树的java实现 - lovewr - 远香清梦
  • 前一点说结点中的数据根据实际情况而定,再举个例子。“题目:给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置。”对于这个题目,显然结点中就存储单词第一次出现的位置(假如当前结点是单词结尾)。
import java.util.*;

/**
 * Tries数据结构(字典树) 这里只是最基本的实现,可判断某个单词是否出现过,单词出现频数等,根据需要可做其它扩展
 * 
 * @author
 * 
 */
public class Trie {

	private TrieNode root;
	private char[] characterTable = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
			'i', 'j', 'k',
			'l', // 遍历的时候使用
			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
			'z'};

	public Trie() {
		root = new TrieNode();
	}

	/**
	 * 插入字符串
	 * 
	 * @param word
	 */
	public void insert(String word) {
		TrieNode node = root;
		word = word.trim();
		for (int i = 0; i < word.length(); i++) {
			if (!(node.children.containsKey(word.charAt(i)))) {
				node.children.put(word.charAt(i), new TrieNode());
			}
			node = node.children.get(word.charAt(i));
		}
		node.terminable = true;
		node.count++;
	}

	/**
	 * 查找某个字符串
	 * 
	 * @param word
	 * @return
	 */
	public boolean find(String word) {
		TrieNode node = root;
		for (int i = 0; i < word.length(); i++) {
			if (!(node.children.containsKey(word.charAt(i)))) {
				return false;
			} else {
				node = node.children.get(word.charAt(i));
			}
		}
		return node.terminable; // 即便该字符串在Trie路径中,也不能说明该单词已存在,因为它有可能是某个子串
	}

	/**
	 * 删除某个字符串(必须是个单词,而不是前缀)
	 * 
	 * @param word
	 */
	public void delete(String word) {
		if (!find(word)) {
			System.out.println("no this word.");
			return;
		}
		TrieNode node = root;
		deleteStr(node, word);
	}

	public boolean deleteStr(TrieNode node, String word) {
		if (word.length() == 0) {
			node.terminable = false; // 不要忘了这里信息的更新
			return node.children.isEmpty();
		}
		if (deleteStr(node.children.get(word.charAt(0)), word.substring(1))) {
			node.children.remove(word.charAt(0));
			if (node.children.isEmpty() && node.terminable == false) { // 注意第二个条件,假如有"abcd"与"abc",删除abcd时,要判断中间路径上是不是另一个子串的结束
				return true;
			}
		}
		return false;
	}

	/**
	 * 以字典序输出Tire中所有出现的单词及频数
	 */
	public void traverse() {
		StringBuffer word = new StringBuffer("");
		TrieNode node = root;
		traverseTrie(node, word);
	}

	public void traverseTrie(TrieNode node, StringBuffer word) {
		if (node.terminable) {
			System.out.println(word + "------" + node.count);
			if (node.children.isEmpty())
				return;
		}
		for (int i = 0; i < characterTable.length; i++) {
			if (!(node.children.containsKey(characterTable[i])))
				continue;
			traverseTrie(node.children.get(characterTable[i]),
					word.append(characterTable[i]));
			word.deleteCharAt(word.length() - 1);
		}
	}

}

/**
 * Trie结点类
 * 
 * @author
 * @param <T>
 */
class TrieNode {
	public boolean terminable; // 是不是单词结尾(即叶子节点)
	public int count; // 单词出现频数
	public Map<Character, TrieNode> children = null;

	public TrieNode() {
		terminable = false;
		count = 0;
		children = new HashMap<Character, TrieNode>();
	}
}
 
转自:http://blog.csdn.net/harry_lyc/article/details/7423326
http://www.tuicool.com/articles/EBB7Fr

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值