🔥无损压缩🔥哈夫曼算法

一、前言

今天了解一下压缩软件底层使用的什么算法,介绍一下常见的两种格式压缩算法,如下表,本文主要介绍DEFLATE中的哈夫曼算法

格式 算法 压缩软件
RAR Roshal Archive WinRaar
ZIP LZ77和哈夫曼算法 7-Zip

二、算法简介

压缩"hello world",根据整组数据中符号出现的频率高低,决定如何给符号编码。如果符号出现的频率越高,则给符号的码越短,相反符号的号码越长。

  1. 首先将这个文本中的字符提取出来,分别统计各个字符出现的频次 (h:1, e:1, l:3, o:2, w:1, r:1, d:1, 空格: 1)
  2. 构建哈夫曼树,每一轮都选择权重最小的两个字符相加,直至顶部只有一个节点。
  1. 压缩,将"hello world"用编码代替 01100111000001011110001010100110,压缩后占32bit。压缩前按UTF-8编码,1个英文字符占1个字节,11 * 8 = 88bit,压缩率为63.64%
  2. 解压,从01100111000001011110001010100110最左侧开始,先取出"0"去哈夫曼树中查找是否有对应的字符,如果没有就取"01"依次向后进行。

三、算法实现

javascript 复制代码
// 编码器
class HuffmanNode {
  constructor(char, freq) {
    this.char = char;
    this.freq = freq;
    this.left = null;
    this.right = null;
  }
}

function buildHuffmanTree(charFreq) {
  let nodes = charFreq.map(item => new HuffmanNode(item.char, item.freq));

  while (nodes.length > 1) {
    nodes = nodes.sort((a, b) => a.freq - b.freq);
    const left = nodes.shift();
    const right = nodes.shift();
    const parent = new HuffmanNode(null, left.freq + right.freq);
    parent.left = left;
    parent.right = right;
    nodes.push(parent);
  }

  return nodes[0];
}

function buildHuffmanCodes(node, currentCode, codes) {
  if (node.char !== null) {
    codes[node.char] = currentCode;
    return;
  }

  if (node.left !== null) {
    buildHuffmanCodes(node.left, currentCode + '0', codes);
  }

  if (node.right !== null) {
    buildHuffmanCodes(node.right, currentCode + '1', codes);
  }
}

function huffmanEncode(text) {
  const charFreq = [...text].reduce((freqMap, char) => {
    freqMap[char] = (freqMap[char] || 0) + 1;
    return freqMap;
  }, {});

  const huffmanTree = buildHuffmanTree(Object.entries(charFreq));
  const huffmanCodes = {};
  buildHuffmanCodes(huffmanTree, '', huffmanCodes);

  const encodedText = [...text].map(char => huffmanCodes[char]).join('');

  return {
    encodedText,
    huffmanTree,
    huffmanCodes,
  };
}
javascript 复制代码
// 解码器
function huffmanDecode(encodedText, huffmanTree) {
  let decodedText = '';
  let currentNode = huffmanTree;

  for (const bit of encodedText) {
    currentNode = bit === '0' ? currentNode.left : currentNode.right;

    if (currentNode.char !== null) {
      decodedText += currentNode.char;
      currentNode = huffmanTree; // 重置为根节点,继续下一个编码的解码
    }
  }

  return decodedText;
}

四、使用场景

  • 做App、游戏时,本地存储数据
  • 通信时压缩传输数据
相关推荐
海鸥两三3 分钟前
登录页面form表单
前端·javascript·css
[H*]4 分钟前
Flutter框架跨平台鸿蒙开发——Pattern Matching模式匹配
android·javascript·flutter
光影少年8 分钟前
前端如何开发ai生成图片及流式回答
前端·人工智能·langchain
风象南8 分钟前
像 ChatGPT 一样丝滑:Spring Boot 如何实现大模型流式(Streaming)响应?
java·spring boot·后端
Java程序员威哥10 分钟前
Spring Boot 3.x 云原生终极适配:GraalVM 原生镜像构建 + Serverless 生产级部署(完整实战+最优模板)
java·开发语言·spring boot·后端·云原生·serverless·maven
qq_124987075312 分钟前
基于微信小程序宠物服务系统(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·毕业设计·宠物
MC丶科7 小时前
【SpringBoot常见报错与解决方案】中文乱码?Spring Boot 统一解决前后端中文乱码问题(含 Postman 测试)!别再百度“加 UTF-8”了!
spring boot·后端·postman
玫城10 小时前
[ VUE ] 封装通用数组校验组件,el-input内使用
前端·javascript·vue.js
XXOOXRT12 小时前
基于SpringBoot的加法计算器
java·spring boot·后端·html5
moxiaoran575313 小时前
Go语言的错误处理
开发语言·后端·golang