`
543089122
  • 浏览: 149661 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

简单_Trie树与三叉Trie树

阅读更多
package sunfa.tree;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 参考:http://book.51cto.com/art/201106/269044.htm
 * Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种
 * 。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计
 * 。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
 * 
 * 网上有许多人错误的把Trie树理解为二叉的,其实Trie树可以是二叉,也可以是多叉的,
 * 本例建立的就是多叉的Trie树,每个节点的子节点集合是一个HashMap,可以这样理解:
 * 根节点下面有N个子节点,第K个子节点下面也是N个子节点。
 * 
 * Trie树的查询次数和key是有关系的,key的长度决定了树的深度。
 * Trie是典型的以空间还时间的快速查找树,适合于对速度要求非常高的场景。
 * 像lucene啊,搜索引擎啊,黑名单啊等就大量使用到Trie树。
 * 最后不的不说Trie对空间的浪费是及其大的。
 * 
 */
public class TrieTreeDemo1 {

	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		TrieTreeDemo1 tree = new TrieTreeDemo1();
		for (int i = 0; i < 20; i++) {
			map.put("key,value" + i, "value" + i);
			tree.addWord("key,value" + i, "value" + i);
		}
		System.out.println("search:");
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next().toString();
			System.out.println(tree.search(key));
		}
		System.out.println(tree.search("ke1"));
	}

	private Entry root = new Entry();

	public void addWord(String key, String o) {
		Entry node = root;
		for (int i = 0; i < key.length(); i++) {
			char c = key.charAt(i);
			if (node.children.get(c) == null) {
				node.children.put(c, new Entry(c));
			}
			node = node.children.get(c);
		}
		node.o = o;
	}

	public Object search(String key) {
		Entry node = root;
		int count = 0;
		for (int i = 0; i < key.length(); i++) {
			count++;
			if (node.children.get(key.charAt(i)) == null)
				return null;
			if (node.children.get(key.charAt(i)).o != null) {
				System.out.println("key:" + key + ",count:" + count);
				return node.children.get(key.charAt(i)).o;
			}
			node = node.children.get(key.charAt(i));
		}
		return null;
	}

	static class Entry {
		Map<Character, Entry> children = new HashMap<Character, TrieTreeDemo1.Entry>();
		char c;
		String o;

		public Entry(char c) {
			this.c = c;
		}

		public Entry() {
		}
	}
}

package sunfa.tree;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 三叉Trie树 http://book.51cto.com/art/201106/269045.htm
 * Trie树应用http://eriol.iteye.com/blog/1166118 三叉Trie树在占用空间上要比N叉树好的多。
 * 在一个三叉搜索树(Ternary Search
 * Trie)中,每一个节点包括一个字符,但和数字搜索树不同,三叉搜索树只有三个指针:一个指向左边的树;一个指向右边的树
 * ;还有一个向下,指向单词的下一个数据单元
 * 。三叉搜索树是二叉搜索树和数字搜索树的混合体。它有和数字搜索树差不多的速度但是和二叉搜索树一样只需要相对较少的内存空间。
 * 树是否平衡取决于单词的读入顺序。如果按排序后的顺序插入
 * ,则生成方式最不平衡。单词的读入顺序对于创建平衡的三叉搜索树很重要,但对于二叉搜索树就不太重要。通过选择一个排序后数据单元集合的中间值
 * ,并把它作为开始节点,我们可以创建一个平衡的三叉树。可以写一个专门的过程来生成平衡的三叉树词典。
 * 
 * Patricia Tree 简称PAT tree。 它是 trie 结构的一种特殊形式。是目前信息检索领域应用十分成功的索引方
 * http://hxraid.iteye.com/blog/topic?show_full=true
 */
public class TernarySearchTrie {
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		int size = 20;
		TernarySearchTrie tree = new TernarySearchTrie();
		for (int i = 0; i < size; i++) {
			map.put("tkey" + i, "value" + i);
			tree.addWord("tkey" + i);
		}
		System.out.println("search:");
		Iterator<String> it = map.keySet().iterator();
		while (it.hasNext()) {
			String key = it.next().toString();
			Entry node = tree.search(key);
			System.out.println(node.data.get("value") + ",查找次数:"
					+ node.data.get("count"));
		}
	}

	private Entry root = new Entry();

	public Entry addWord(String key) {
		if (key == null || key.trim().length() == 0)
			return null;
		// 调试的时候发现个问题很是不明白,为什么根节点一开始就有不为NULL的right节点,并且这个right节点的splitchar是k
		// 终于发现了,java程序在调试的时候可能存在一个预编译的问题,某些链表式的对象调试的时候DEBUG信息不是很准备,甚至错误,比如链表啊,i++等操作调试就会看到错误的信息,这样的情况用打印语句调试算了。
		Entry node = root;
		int i = 0;
		while (true) {
			int diff = key.charAt(i) - node.splitchar;
			char c = key.charAt(i);
			if (diff == 0) {// 当前单词和上一次的相比较,如果相同
				i++;
				if (i == key.length()) {
					node.data = new HashMap<Object, Object>();
					node.data.put("value", key);
					return node;
				}
				if (node.equals == null)
					node.equals = new Entry(key.charAt(i));// 这里要注意,要获取新的单词填充进去,因为i++了
				node = node.equals;
			} else if (diff < 0) {// 没有找到对应的字符,并且下一个左或右节点为NULL,则会一直创建新的节点
				if (node.left == null)
					node.left = new Entry(c);
				node = node.left;
			} else {
				if (node.right == null)
					node.right = new Entry(c);
				node = node.right;
			}
		}
	}

	public Entry search(String key) {
		if (key == null || key.trim().length() == 0)
			return null;
		Entry node = root;
		int count = 0, i = 0;
		while (true) {
			if (node == null)
				return null;
			int diff = key.charAt(i) - node.splitchar;
			count++;
			if (diff == 0) {
				i++;
				if (i == key.length()) {
					node.data.put("count", count);
					return node;
				}
				node = node.equals;
			} else if (diff < 0) {
				node = node.left;
			} else {
				node = node.right;
			}
		}
	}

	/**
	 * 三叉Trie树存在3个节点,左右子节点和二叉树类似,以前key都是存放在二叉树的当前节点中,在三叉树中单词是存放在中间子树的。
	 */
	static class Entry {
		Entry left;
		Entry right;
		Entry equals;// 比对成功就放到中间节点
		char splitchar;// 单词
		Map<Object, Object> data;// 扩展数据域,存放 检索次数,关键码频率等信息。

		public Entry(char splitchar) {
			this.splitchar = splitchar;
		}

		public Entry() {
		}
	}
}
分享到:
评论

相关推荐

    C#编写的三叉Trie树

    对于一般的Trie树的数据结构,它的实现简单但是空间效率极低。三叉搜索树使用了一种聪明的手段去解决字典树的内存问题(空的指针数组)。为了避免多余的指针占用内存,每个节点不再用数组来表示,而是表示成“树中有...

    生锈的三元搜索树集合,并尽可能使用与std :: collections类似的API。-Rust开发

    三元搜索树是trie的一种类型(有时称为前缀树),其中将节点排列在其中一种类似于二叉搜索树的方式,但是最多具有三个子级,而不是二叉树的限制,与其他前缀树一样,三叉搜索树可以用作关联映射结构,并具有增量字符...

    AC-TernarySearchTrie

    使用三叉树构建AC自动机实现大规模字符串的匹配 模式串数量127W,待搜索文件大小为700M+

    Java数据结构与算法源代码

    a.10 个数据结构:数组,链表,栈,队列,散列表,三叉树,堆,跳表图,Trie 树。 b.10 个算法:递归,排序,二分查找,搜索,哈希算法,贪心算法,分治算法,回溯算法,动态规划,字符串匹配算法。 四。学习技巧 ...

    数据结构(王)c元代码

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 范例1-102...

    数据结构算法实现(严蔚敏版配套实现程序)

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 范例1-102...

    数据结构算法实现(严蔚敏版配套实现程序)

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 范例1-102...

    数据结构 严蔚敏 代码

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 范例1-102...

    C 开发金典

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 ...

    C语言通用范例开发金典.part2.rar

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 ...

    C语言通用范例开发金典.part1.rar

    范例1-100 按关键字符串遍历Trie树 301 ∷相关函数:SearchTrie函数 1.6.8 哈希表的基本操作 306 范例1-101 哈希表的基本操作 306 ∷相关函数:SearchHash函数 1.7 图 311 1.7.1 图的邻接矩阵存储表示 311 ...

Global site tag (gtag.js) - Google Analytics