1.Hash树

理想的情况是希望不经过任何比较,一次存取便能得到所查的记录, 那就必须在记的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和一个唯一的存储位置相对应。因而在查找时,只要根据这个对应关系f找到 给定值K的像f(K)。由此,不需要进行比较便可直接取得所查记录。在此,我们称这个对应关系为哈希(Hash)函数,按这个思想建立的表为哈希表

在哈希表中对于不同的关键字可能得到同一哈希地址,这种现象称做冲突。在一般情况下,冲突只能尽可能地减少,而不能完全避免。因为哈希函数是从关键字集合 到地址集合的映像。通常关键字的集合比较大,它的元素包括所有可能的关键字,而地址集合的元素仅为哈希表中的地址值。在一般情况下,哈希函数是一个压缩映像函数,这就不可避免的要产生冲突。



哈希树的理论基础


质数分辨定理
简单地说就是:n个不同的质数可以“分辨”的连续整数的个数和他们的乘积相等。“分辨”就是指这些连续的整数不可能有完全相同的余数序列。

例如:
从2起的连续质数,连续10个质数就可以分辨大约M(10) =2*3*5*7*11*13*17*19*23*29= 6464693230 个数,已经超过计算机中常用整数(32bit)的表达范围。连续100个质数就可以分辨大约M(100) = 4.711930 乘以10的219次方。

插入


我们选择质数分辨算法来建立一棵哈希树。
选择从2开始的连续质数来建立一个十层的哈希树。第一层结点为根结点,根结点下有2个结点;第二层的每个结点下有3个结点;依此类推,即每层结点的子节点数目为连续的质数。到第十层,每个结点下有29个结点。
同一结点中的子结点,从左到右代表不同的余数结果。
例如:第二层结点下有三个子节点。那么从左到右分别代表:除3余0,除3余1,除3余2.
对质数进行取余操作得到的余数决定了处理的路径

下面我们以随机的10个数的插入为例,来图解HashTree的插入过程

Hash树(散列树)和Trie树(字典树、前缀树)_第1张图片


2.Trie树


  字典树(Trie)可以保存一些字符串->值的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。
  Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。Hash 表号称是 O(1) 的,但在计算 hash 的时候就肯定会是 O(k) ,而且还有碰撞之类的问题;Trie 的缺点是空间消耗很高。
      Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
      Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。


以英文单词构建的字典树为例,这棵Trie树中每个结点包括26个孩子结点,因为总共有26个英文字母(假设单词都是小写字母组成)。

 下面我们有and,as,at,cn,com这些关键词,那么如何构建trie树呢?


Hash树(散列树)和Trie树(字典树、前缀树)_第2张图片


Hash树(散列树)和Trie树(字典树、前缀树)_第3张图片


从上面的图中,我们或多或少的可以发现一些好玩的特性。

      第一:根节点不包含字符,除根节点外的每一个子节点都包含一个字符。

      第二:从根节点到某一节点,路径上经过的字符连接起来,就是该节点对应的字符串。

      第三:每个单词的公共前缀作为一个字符节点保存。




参考文章:

       Trie树:应用于统计和排序     http://blog.csdn.net/hguisu/article/details/8131559

     图文详解HashTree(哈希树)   http://blog.csdn.net/yang_yulei/article/details/46337405