11. 最优前缀码

本文探讨了如何基于字符集及其频率,构建最优前缀码——哈夫曼编码。通过创建并合并二叉树,最终形成哈夫曼树,实现高效的数据压缩。文章详细介绍了哈夫曼树的构建过程及编码规则,展示了算法的时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最优前缀码

1. 问题

给定字符集C={x1, x2, …, xn}和每个字符的频率f(xi),求关于 C 的一个最优前缀码。

2. 解析

1.根据给定的n个权值{w1,w2,…,wn}构成n棵二叉树的合集F={T1, T2, …, Tn}, 其中每棵二叉树Ti中只有一个带权为wi根结点,其左右子树均为空。
2.在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左右子树上根结点的权值之和。
3.在F中删除这两棵树,同时将其新得到的二叉树加入F中。
4.重复2和3步骤,直到F只含一棵树为止。这棵树就是哈夫曼树。
5.规定哈夫曼树的左分支为0,右分支为1,从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码。

3. 设计

PriorityQueue<HuffmanNode> q =
                new PriorityQueue<HuffmanNode>(n, new MyComparator());

        for(int i = 0; i < n; i++){
            HuffmanNode hn = new HuffmanNode();
            hn.c = charArray[i];
            hn.weight = charFreq[i];
            hn.left = null;
            hn.right = null;
            q.add(hn);
        }
HuffmanNode root = null;
        while(q.size() > 1){
            HuffmanNode x = q.peek();
            q.poll();
            HuffmanNode y = q.peek();
            q.poll();
            HuffmanNode temp = new HuffmanNode();
            temp.c = '-';
            temp.weight = x.weight+y.weight;
            temp.left = x;
            temp.right = y;
            root = temp;
            q.add(temp);
        }

4. 分析

O(nlogn)频率排序;for 循环 O(n),插入操作 O(logn),算法时间复杂
度是 O(nlogn)

5. 源码

https://github.com/Marshmello11/Algorithm/tree/master/Experiment_11

### 最优前缀码概述 最优前缀码是一种特殊的编码方式,其中没有任何一个码字是另一个码字的前缀。这种特性确保了编码后的消息可以被唯一解析而不会产生歧义。 #### 编码序列特点 高效性体现在高频字符拥有更短的编码长度,低频字符则对应较长的编码[^1]。这有助于减少整个文件或数据流表示所需的总位数,进而提高传输效率和存储空间利用率。 #### 构造方法 构造最优前缀码通常采用哈夫曼编码的方法: - **频率统计**:计算输入数据集中各个符号出现的概率分布情况。 - **构建最小堆(优先级队列)**:基于这些概率建立一个小顶堆结构,在这里每个叶子结点代表原始字符及其权重(即发生次数),而非叶节点则是由两个子节点合并而成的新内部节点,其权值等于两孩子之和。 - **贪心策略建树**:不断取出当前堆中最轻量级的两个元素并组合成一个新的父节点直到只剩下一个根节点为止,最终形成了一棵完整的二叉树——也就是所谓的哈夫曼树[^2]。 - **分配编码**:沿着该树自上而下遍历每一个分支,向左走标记为`0`,往右记作`1`,由此可获得相应于各终端节点所关联字母的独特二进制串作为它们各自的霍夫曼编码[^3]。 ```python import heapq from collections import defaultdict, Counter def huffman_encoding(data): frequency = dict(Counter(data)) heap = [[weight, [symbol, ""]] for symbol, weight in frequency.items()] heapq.heapify(heap) while len(heap) > 1: lo = heapq.heappop(heap) hi = heapq.heappop(heap) for pair in lo[1:]: pair[1] = '0' + pair[1] for pair in hi[1:]: pair[1] = '1' + pair[1] heapq.heappush(heap, [lo[0]+hi[0]] + lo[1:] + hi[1:]) return sorted(heapq.heappop(heap)[1:], key=lambda p: (len(p[-1]),p)) data = "this is an example of a huffman tree" huffman_code = huffman_encoding(data) print("Symbol".ljust(10) + "Frequency".ljust(10)+ "Huffman Code") for i in huffman_code: print(f"{i[0]}".ljust(10), end="") print(str(data.count(i[0])).ljust(10),end=" ") print(i[1]) ``` #### 应用场景 这类编码广泛应用于各种类型的压缩软件和技术当中,比如ZIP档案格式、JPEG图像标准以及MP3音频编解码器等。它不仅限于文本处理领域,对于多媒体资源同样适用,因为几乎所有形式的数据都可以转换成适合应用此算法的形式来达到节省带宽的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值