哈夫曼树

Posted rookiejw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈夫曼树相关的知识,希望对你有一定的参考价值。

when? what? why? how?

why

为什么会出现哈夫曼树?

what

哈夫曼树有什么用?

什么是哈夫曼树?

哈夫曼树的特点是啥?

how

如何创建哈夫曼树?


为什么会出现哈夫曼树?

效率!!!

比如一所高中有1000个同学进行了一次考试(总分100),现在需要将每个成绩段转换为优、良、中、合格、不合格(已经知道每个分数段多少人)。

技术分享图片

当不合格、合格这块同学比较多时效率比较高,因为大部分人只要比较一次或两次。如果中高分段人比较多那么这时候的效率就比较低了因为大部分人需要比较至少 3 次以上。

技术分享图片

当中间段人比较多时,这个比较方法效率高,大多数人只要比较一到两次,如果两端人比较多那么效率就比较低。

所以,当我们知道每个分数段大概有多少人时,可以将分数段人多的放在顶端减下比较次数,少的放底端。 有这个需求所以 哈夫曼树出现了....(瞎说的)追求效率最高

什么是哈夫曼树?

简单说WPL最小的二叉树

了解几个定义

1.树的路径长度

树的路径长度是从树根到树中每一结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径长度最短。

2.树的带权路径长度(Weighted Path Length of Tree,简记为WPL)

结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数。

结点的带权路径长度:结点到树根之间的路径长度与该结点上权的乘积。

树的带权路径长度 (Weighted Path Length of Tree):定义为树中所有叶结点的带权路径长度之和,通常记为: WPL=(W1L1+W2L2+W3L3+...+WnLn)

其中:Wi 和 Li 分别表示叶结点的权值和根到结点之间的路径长度。
树的带权路径长度亦称为树的代价。

哈夫曼树定义
假设有 n 个权值[W1,W2,....WN],构造有 n 个叶子的二叉树,每个叶子的权值是 n 个权值之一,这样的二叉树可以构造很多个,其中必有一个是带权路径长度最小的,这棵二叉树就称为最优二叉树或哈夫曼树。

哈夫曼树的特点是啥?

  1. 没有度为1的结点
  2. n个叶子结点的哈夫曼树共有2n-1个结点
  3. 哈夫曼树任意非叶借点的左右树交换后仍是哈夫曼树

如何创建哈夫曼树?

class HuffmanTree {
public static HTNode buildHuffmanTree(HeapHNode heap, int[] data) {
    //构建最小堆
    heap.buildMinHeap(heap, data);
    HTNode node =null;
    int num=heap.size;
    //做heap.size - 1 次合并
    for(int i=1;i<num;i++){
        node=new HTNode();
        //从最小堆中删除一个结点作为新结点的做左子节点
        node.left=heap.deleteMin(heap);
        //从最小堆中删除一个结点作为新结点的做右子节点
        node.right=heap.deleteMin(heap);
        node.weight=node.left.weight+node.right.weight;
        //将新结点插入最小堆中
        heap.insert(heap,node);
    }
    //最小堆中的最后一个结点即指向哈夫曼树的树根结点
    return heap.deleteMin(heap);
}
}

时间复杂度分析

  1. 构建最小堆 O(N)
  2. 2(N-1)+1个删除:O(NlogN)
  3. N-1 个插入 :O(NlogN)

所以时间复杂度 O(NlogN)。

结果

数据:100, 34, 67, 78, 98, 55, 44

技术分享图片

源代码:https://github.com/rookieLJ/Tree.git

TestHuffmanTree.java

总结

参考
数据结构 陈越 何钦铭

哈夫曼树的创建是用了最小堆。

哈夫曼树的主要作用

https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fr=aladdin

简单说为了进行哈夫曼编码,这样就可以起到压缩作用.

在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符.例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}.现要求为这些字母设计编码.要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码.显然编码的长度取决报文中不同字符的个数.若报文中可能出现26个不同字符,则固定编码长度为5.然而,传送报文时总是希望总长度尽可能短.在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码.

以上是关于哈夫曼树的主要内容,如果未能解决你的问题,请参考以下文章

怎么样用c语言程序编码哈夫曼树?

数据结构中哈夫曼树的应用(C语言)

百度看到您的 请问 那个哈夫曼树和哈夫曼编码。。。跪谢!

如何构造哈夫曼树

数据结构 赫夫曼树

哈夫曼树