JavaScript 规范霍夫曼编码

         霍夫曼编码是一种无损数据压缩算法,其中数据中的每个字符都分配有可变长度的前缀代码。出现频率最低的字符获得最大代码,出现频率最高的字符获得最小代码。使用这种技术对数据进行编码非常简单且高效。但是,解码使用此技术生成的比特流效率低下。解码器(或解压缩器)需要了解所使用的编码机制,以便将编码数据解码回原始字符。 

        因此,需要将编码过程的信息与编码数据一起作为字符表及其对应代码传递给解码器。在对大量数据进行常规霍夫曼编码时,此表会占用大量内存空间,而且如果数据中存在大量唯一字符,则由于存在代码本,压缩(或编码)数据大小会增加。因此,为了使解码过程在计算上高效,同时仍保持良好的压缩率,引入了规范霍夫曼码。 

        在标准霍夫曼编码中,使用为每个符号生成的标准霍夫曼代码的位长。首先根据符号的位长按非递减顺序对符号进行排序,然后根据每个位长按字典顺序对符号进行排序。第一个符号获得一个全为零且长度与原始位长相同的代码。对于后续符号,如果符号的位长等于前一个符号的位长,则将前一个符号的代码加一并分配给当前符号。 

        否则,如果符号的位长大于前一个符号的位长,则在增加前一个符号的代码后,将零附加到该代码上,直到长度等于当前符号的位长,然后将代码分配给当前符号。 
此过程继续处理其余符号。 

以下示例说明了该过程:

考虑以下数据: 

特点频率
A10
b1
C15
d7

生成的标准霍夫曼码的位长度为:  

特点霍夫曼编码位长度
A112
b1003
C01
d1013
  • 步骤 1:根据位长对数据进行排序,然后根据每个位长度按字典顺序对符号进行排序。 
特点位长度
C1
A2
b3
d3
  • 步骤 2:为第一个符号的代码分配与位长相同数量的“0”。 
    ‘c’的代码:0
    下一个符号‘a’的位长为 2 > 前一个符号‘c’的位长为 1。将前一个符号的代码增加 1 并附加 (2-1)=1 个零并将代码分配给‘a’。 
    ‘a’的代码:10
    下一个符号‘b’的位长为 3 > 前一个符号‘a’的位长为 2。将前一个符号的代码增加 1 并附加 (3-2)=1 个零并将代码分配给‘b’。 
    ‘b’的代码:110
    下一个符号‘d’的位长为 3 = 前一个符号‘b’的位长为 3。将前一个符号的代码增加 1 并将其分配给‘d’。 
    ‘d’的代码:111
  • 步骤3:最终结果。  
特点规范霍夫曼编码
C0
A10
b110
d111

        该方法的基本优点是,传递给解码器的编码信息可以更紧凑、更节省内存。例如,可以简单地将字符或符号的位长度传递给解码器。由于长度是连续的,因此可以轻松根据长度生成规范代码。 
有关使用 Huffman 树生成 Huffman 代码的信息,请参阅之前的文章如下:

c语言:c语言 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)_霍夫曼的贪婪c语言-CSDN博客

c++:c++ 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)_霍夫曼的贪婪算法设计核心代码-CSDN博客

c#:C# 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客 

c++ STL:c++ STL 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客 

java:java 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客 

python:python 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客 

javascript:JavaScript 霍夫曼编码 | 贪婪算法(Huffman Coding | Greedy Algo)-CSDN博客 

方法:一种简单有效的方法是为数据生成一棵哈夫曼树,并使用类似于 Java 中的 TreeMap 的数据结构来存储符号和位长,以使信息始终保持排序。然后可以使用增量和按位左移运算来获取规范代码。 

执行:

// Node class to store data and its frequency
class Node {
    constructor(char, freq) {
        this.char = char;
        this.freq = freq;
        this.left = null;
        this.right = null;
    }

    // Defining comparators less_than and equals
    lessThan(other) {
        return this.freq < other.freq;
    }

    equals(other) {
        if(other == null) {
            return false;
        }
        if(!(other instanceof Node)) {
            return false;
        }
        return this.freq == other.freq;
    }
}

// Function to generate Huffman codes
function code_gen(root, code_length, code_map) {
    if (root == null) {
        return;
    }

    if (root.left == null && root.right == null) {
        if(!code_map[code_length.length]) {
            code_map[code_length.length] = [];
        }
        code_map[code_length.length].push(root.char);
    }

    code_gen(root.left, code_length + '0', code_map);
    code_gen(root.right, code_length + '1', code_map);
}

// Main function implementing Huffman coding
function testCanonicalHC(chararr, freq) {
    // Priority queue to store heap tree
    let q = [];
    for(let i = 0; i < chararr.length; i++) {
        q.push(new Node(chararr[i], freq[i]));
    }
    q.sort((a, b) => a.lessThan(b) ? -1 : a.equals(b) ? 0 : 1);

    while (q.length > 1) {
        let left = q.shift();
        let right = q.shift();

        let merged = new Node(null, left.freq + right.freq);
        merged.left = left;
        merged.right = right;

        q.push(merged);
        q.sort((a, b) => a.lessThan(b) ? -1 : a.equals(b) ? 0 : 1);
    }

    let root = q.shift();
    let code_map = {};
    code_gen(root, "", code_map);

    // Generate Canonical Huffman codes
    let canonical_map = {};
    let c_code = 0;
    let lengths = Object.keys(code_map).sort((a, b) => a - b);
    for(let length of lengths) {
        code_map[length].sort();
        for(let char of code_map[length]) {
            canonical_map[char] = c_code.toString(2).padStart(length, '0');
            c_code += 1;
        }
        c_code <<= 1;
    }

    // Print Canonical Huffman codes
    let chars = Object.keys(canonical_map);
    chars.sort((a, b) => canonical_map[a].length - canonical_map[b].length || a.localeCompare(b));
    for(let char of chars) {
        console.log(`${char}: ${canonical_map[char]}`);
    }
}

// Driver code
let chararr = ['a', 'b', 'c', 'd'];
let freq = [10, 1, 15, 7];
testCanonicalHC(chararr, freq);

输出:
c:0
a:10
b:110
d:111   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/28504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Parallels Desktop 19 激活码 - 苹果 Mac 最新版 PD 19激活密钥虚拟机下载 (支持Win11/macOS Sonoma)

Parallels Desktop 被称为 macOS 上强大的虚拟机软件。可以在 Mac 下同时模拟运行 Win、Linux、Android 等多种操作系统及软件而不必重启电脑&#xff0c;并能在不同系统间随意切换。 最新版 Parallels Desktop 19 (PD19) 完全支持 macOS Sonoma、Ventura 和 Windows 11 / Win…

【Ardiuno】实验使用OPT语音模块播放语音(图文)

当我们需要在程序中播放语音内容时&#xff0c;就需要使用到语音模块&#xff0c;今天我们就来实验一下使用OPT语音模块来方法语音。 const int voicePin 5; const int voiceBusyPin 18; const int testLEDPin 2;unsigned long pmillis 0;int busyVal 0; …

LeetCode | 125.验证回文串

这道题一开始的想法是把原字符串的非数字英文字符去掉&#xff0c;然后判断剩下的字符串是否为回文串即可&#xff0c;其中去掉非数字英文字符可以遍历一遍字符串依次处理&#xff0c;也可以用正则表达式&#xff0c;然后判断是否是回文串只需要两个指针&#xff0c;一头一尾&a…

OpenCV目标识别

一 图像轮廓 具有相同颜色或强度的连续点的曲线。 图像轮廓的作用 可以用于图像分析 物体的识别与检测 注意 为了检测的准确性&#xff0c;需要先对图像进行二值化或Canny操作。 画轮廓时会修改输入的图像。 轮廓查找的API findContours(img,mode,ApproximationMode,...)…

代码随想录算法训练营第十天| 232.用栈实现队列|225. 用队列实现栈|20. 有效的括号|1047. 删除字符串中的所有相邻重复项

232.用栈实现队列 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;栈的基本操作&#xff01; | LeetCode&#xff1a;232.用栈实现队列_哔哩哔哩_bilibili 知道要用两个栈实现&#xff0c;具体咋做忘了。队列的特性是先进先出&#xff0c;栈是先进后出&#xff0c;入队操…

upload-labs第八关教程

upload-labs第八关教程 一、源代码分析代码审计 二、绕过分析点绕过上传eval.php使用burp suite进行抓包修改放包&#xff0c;查看是否上传成功使用中国蚁剑进行连接 一、源代码分析 代码审计 $is_upload false; $msg null; if (isset($_POST[submit])) {if (file_exists(U…

推箱子-小游戏

学习目标&#xff1a; 巩固Java基础&#xff0c;数据类型、二维数组、条件语句等&#xff1b; 效果展示&#xff1a;

CSS【详解】样式选择器的优先级(含提升优先级的方法)

数值越大&#xff0c;优先级越高&#xff0c;尽量保持较低的优先级&#xff0c;以便使用更高优先级的选择器重置样式 0级——通配选择器、选择符和逻辑组合伪类。逻辑组合伪类有:not()、:is()和:where等&#xff0c;这些伪类本身并不影响CSS优先级&#xff0c;影响优先级的是括…

Python基础用法 之 变量

1.变量的定义 变量的作用&#xff1a;是⽤来保存数据的。定义的语法&#xff1a;变量名 数据值使用&#xff1a;直接使⽤变量名 即可使⽤变量中存储的数据。注意&#xff1a;变量必须先定义后使用。 (即 必须 先存⼊数据 才能 获取数据) 。 # 需求 1, 定义⼀个变量 保存你的名…

flutter中采用腾讯云COS进行图片存储

首先配置文件添加 flutter_cos: ^0.0.3 添加COS配置 import dart:io; import dart:io; import dart:convert; import package:http/http.dart as http; import package:http/http.dart;class CosConfig {final String appid;final String region;final String bucket;CosCon…

(超详细)基于动态顺序表实现简单的通讯录项目

前言&#xff1a; 我们在上一章节用c语言实现了线性表中的的动态顺序表&#xff0c;那么顺序表就只是顺序表吗&#xff1f;当然不是&#xff0c;使用顺序表结构可以实现很多项目&#xff0c;许多项目的数据结构都会用到顺序表&#xff0c;本章节我们就要使用顺序表实现一个简易…

等保一体机

等保一体机是面向等保场景推出的合规型安全防护产品。基于“一个中心&#xff0c;三重防护”的设计理念&#xff0c;通过内置全面、多样的安全能力&#xff0c;为政府、医疗、教育、企业等中小型客户提供快速合规、按需赋能的一站式等保合规解决方案。 等保一体机要求管理网络和…

jEasyUI 使用标记创建树形菜单

jEasyUI 使用标记创建树形菜单 jEasyUI 是一个基于 jQuery 的用户界面插件集合&#xff0c;它提供了一系列的组件&#xff0c;如菜单、窗口、表格等&#xff0c;以帮助开发者快速构建交互式的网页应用。树形菜单&#xff08;Tree Menu&#xff09;是 jEasyUI 中常用的组件之一…

【论文阅读】AttnDreamBooth | 面向文本对齐的个性化图片生成

文章目录 1 动机2 方法3 实验 1 动机 使用灵活的文本控制可以实现一些特定的概念的注入从而实现个性化的图片生成。 最经典的比如一些好玩的动漫人物的概念&#xff0c;SD大模型本身是不知道这些概念的&#xff0c;但是通过概念注入是可以实现的从而生成对应的动漫人物 两个…

创建阿里云的免费镜像仓库

1、登录 阿里云 首先进入阿里云的官网&#xff0c;如果没有注册的需要先注册&#xff0c;这里就不过多的讲解了。 2、搜索 登录完毕后点击右上角的控制台 进入管理页面。或者直接在搜索框中输入容器镜像服务 点击进入 这里我是已经开通过了&#xff0c;如果你还没有开通的…

SpringBoot 第一天

什么是Spring Boot 学习过spring&#xff0c;并且做过项目的估计都经历过&#xff0c;xml文件的繁杂配置&#xff0c;让人眼花缭乱&#xff0c;且极易出错&#xff0c;因此 Spring 一度被称为“配置地狱” 为了简化 Spring 应用的搭建和开发过程&#xff0c;Pivotal 团队在 S…

算法训练营day60

题目1&#xff1a;647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int countSubstrings(string s) {vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));int reslut 0;for(int i s.size() - 1;i > 0;…

什么是git?

前言 Git 是一款免费、开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。是的&#xff0c;我对git的介绍就一条&#xff0c;想看简介的可以去百度一下&#x1f618;&#x1f618;&#x1f618; 为什么要用git&#xff1f; OK&#xff0c;想象一下…

《C语言》文件操作

文章目录 一、认识文件1、文件的概念2、程序文件3、数据文件4、文件名 三、二进制文件和文本文件四、文件的打开和关闭1、流2、标准流3、文件指针4、文件的关闭和打开 四、文件的顺序读写文件的随机读写1、fseek2、ftell3、rewind4.int origin 一、认识文件 主要讨论数据文件 1…

代码随想三刷二叉树篇1

代码随想三刷二叉树篇1 144. 二叉树的前序遍历题目代码 145. 二叉树的后序遍历题目代码 94. 二叉树的中序遍历题目代码 102. 二叉树的层序遍历题目代码 107. 二叉树的层序遍历 II题目代码 199. 二叉树的右视图题目代码 637. 二叉树的层平均值题目代码 515. 在每个树行中找最大值…