霍夫曼压缩中,将比特写入大端字节序的方式是否正确?
霍夫曼压缩大端字节序存储二进制编码的实现方案
嘿,我完全懂你在霍夫曼压缩里卡到的这个点——大端字节序下把零散的二进制编码塞进unsigned char里,说起来简单但实际操作总容易搞混比特位的位置,尤其是像1101这种非整字节的编码,查帖子找不到清晰答案确实闹心!我来给你一步步讲明白:
核心逻辑:大端字节序的比特填充规则
大端的核心是高位比特优先存储,也就是说我们要从unsigned char的最高位(第7位,二进制从左到右数第一个位置)开始,往最低位(第0位)依次填充霍夫曼编码。比如你要存1101这4位,最终的字节应该是11010000——前4位是你要存的编码,剩下的低位补0留着后续填充。
具体操作步骤(附代码示例)
假设我们从初始值为00000000的unsigned char开始:
1. 存入单段短编码(比如1101,4位)
首先把编码转换成十进制(1101对应十进制13),然后根据编码长度计算左移位数:左移位数 = 8 - 编码长度。因为要把编码放到字节的最高位区域,所以:
unsigned char byte = 0; // 初始00000000 // 1101对应十进制13,左移4位(8-4)放到高位 byte |= (13 << 4); // 现在byte的值是0xD0,二进制为11010000
2. 继续填充后续编码(比如再存10,2位)
如果后续还有编码要存,需要先记录已经用掉的比特位数(这里已经用了4位),然后计算新编码的左移位数:左移位数 = 8 - 已用位数 - 新编码长度。把新编码左移后和当前字节做或操作,就能把编码填到下一段高位位置:
// 10对应十进制2,已用4位,新编码2位,左移位数=8-4-2=2 byte |= (2 << 2); // 现在byte的值是0xD8,二进制为11011000
3. 处理跨字节的长编码
如果遇到剩余比特位不够存当前编码的情况(比如当前字节还剩3位,但要存5位的编码10110),拆分两步处理:
- 先取编码的前3位
101(十进制5),直接填充到当前字节的剩余位置:
// 当前byte已用5位,剩余3位 byte |= 5; // 5是101,直接填到剩余低位 // 现在byte是原已填充的5位 + 101
- 剩下的2位
10(十进制2),放到新的unsigned char里,左移6位(8-2)放到新字节的高位:
unsigned char new_byte = 0; new_byte |= (2 << 6); // new_byte的值是0x80,二进制为10000000
总结一下关键思路
每次填充编码时,都要先确定当前字节的剩余可用高位位置,把编码左移到对应位置后通过或操作合并到字节里——这样就能严格遵循大端字节序的存储规则,保证霍夫曼编码的正确存储和后续解码。
内容的提问来源于stack exchange,提问作者Ji Kang
相关产品推荐
相关产品推荐

