数据结构 - 哈夫曼树 - 字典树 - 面试中可能会涉及的树知识点

数据结构 - 哈夫曼树 - 哈希树 - 字典树 - 面试中可能会涉及的树知识点

数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组、链表)、栈与队列(二叉树、二叉查找树、平衡二叉树、红黑树)、

本文主要介绍中的一些种类。包括

  • 哈夫曼树
  • 字典树

哈夫曼树

哈夫曼树是一种带权路径长度最短二叉树,也称为最优二叉树。下面用一幅图来说明。

数据结构 - 哈夫曼树 - 字典树 - 面试中可能会涉及的树知识点_第1张图片

它们的带权路径长度分别为:
图a: WPL=5*2+7*2+2*2+13*2=54
图b: WPL=5*3+2*3+7*2+13*1=48
可见,图b的带权路径长度较小,我们可以证明图b就是哈夫曼树(也称为最优二叉树)。

一、如何构建哈夫曼树?

一般可以按下面步骤构建:

  1. 将所有左,右子树都为空的作为根节点。
  2. 在森林中选出两棵根节点的权值最小的树作为一棵新树的左,右子树,且置新树的附加根节点的权值为其左,右子树上根节点的权值之和。注意,左子树的权值应小于右子树的权值。
  3. 从森林中删除这两棵树,同时把新树加入到森林中。
  4. 重复2,3步骤,直到森林中只有一棵树为止,此树便是哈夫曼树。

下面是构建哈夫曼树的图解过程:

数据结构 - 哈夫曼树 - 字典树 - 面试中可能会涉及的树知识点_第2张图片

二、哈夫曼编码

利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码

就拿上图例子来说:
A,B,C,D对应的哈夫曼编码分别为:111,10,110,0

用图说明如下:

数据结构 - 哈夫曼树 - 字典树 - 面试中可能会涉及的树知识点_第3张图片

记住,设计电文总长最短的二进制前缀编码,就是以n个字符出现的频率作为权构造一棵哈夫曼树,由哈夫曼树求得的编码就是哈夫曼编码。


字典树:Trie树

Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。字典树(Trie)可以保存一些 字符串 -> 值 的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。

Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) ,其中 k 为 key 的长度,与 Trie 中保存了多少个元素无关。Hash 表号称是 O(1) 的,但在计算 hash 的时候就肯定会是 O(k) ,而且还有碰撞之类的问题;Trie 的缺点是空间消耗很高

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

Trie树的基本性质可以归纳为:
(1)根节点不包含字符,除根节点意外每个节点只包含一个字符。
(2)从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
(3)每个节点的所有子节点包含的字符串不相同。
(4)如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。
(5)插入查找的复杂度为O(n),n为字符串长度。

基本思想(以字母树为例):
1、插入过程
对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点标记为红色,表示该单词已插入Trie树。
2、查询过程
同样的,从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未标记为红色,则表示该单词不存在,若最后的节点标记为红色,表示该单词存在。

字典树的数据结构

一般可以按下面步骤构建:

利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。

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

则可声明包含Trie树的结点信息的结构体:

typedef struct Trie_node
{
    int count;                    // 统计单词前缀出现的次数
    struct Trie_node* next[26];   // 指向各个子树的指针
    bool exist;                   // 标记该结点处是否构成单词  
}TrieNode , *Trie;

其中next是一个指针数组,存放着指向各个孩子结点的指针。

如给出字符串”abc”,”ab”,”bd”,”dda”,根据该字符串序列构建一棵Trie树。则构建的树如下:

数据结构 - 哈夫曼树 - 字典树 - 面试中可能会涉及的树知识点_第4张图片

你可能感兴趣的:(数据结构)