C#,数值计算——哈夫曼编码与数据压缩技术(Huffman Coding and Compression of Data)源代码

news2024/9/20 10:34:00

1 霍夫曼编码导论

  • 霍夫曼编码是一种基于数据集中符号频率的无损数据压缩形式。
  • 它是一种前缀编码方案,这意味着编码的数据不包含任何冗余比特。
  • 霍夫曼编码广泛应用于各种应用,如图像和视频压缩、数据传输和数据存储。

2 霍夫曼编码的优点

以下是霍夫曼编码的5个优点:

  • 霍夫曼编码是一种有效的数据压缩方法,因为它将较短的代码分配给数据集中出现频率较高的符号。这导致了更高的压缩比。
  • 霍夫曼编码是一种前缀编码方案,这意味着它不需要任何特殊的标记来分隔不同的代码。这使得它易于实现和解码。
  • 霍夫曼编码是一种广泛使用的数据压缩方法,并得到许多软件库和工具的支持,使其易于集成到现有系统中。
  • 霍夫曼编码是一种无损压缩方法,这意味着可以从压缩数据中准确地重建原始数据。
  • 霍夫曼编码是一种简单有效的算法,可以很容易地在软件和硬件上实现。

3 霍夫曼编码的缺点

以下是霍夫曼编码的5个缺点:

  • 霍夫曼编码要求预先知道每个符号的频率,这使得它不太适合于符号分布未知或动态变化的情况。
  • 霍夫曼树可能很复杂,很难理解,这使得调试和维护代码变得更加困难。
  • 编码过程可能耗时且计算成本高昂,尤其是对于大型数据集。
  • 霍夫曼编码并不总是最有效的压缩方法,可能还有其他方法可以为给定的数据集提供更好的压缩比。
  • 在只有很少的唯一符号或符号已经被高度压缩的情况下,霍夫曼编码对数据的效果可能较差。

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Huffman Coding and Compression of Data
    /// </summary>
    public class Huffcode
    {
        private int nch { get; set; }
        private int nodemax { get; set; }
        private int mq { get; set; }
        private int ilong { get; set; }
        private int nlong { get; set; }
        private int[] ncod { get; set; }
        private int[] left { get; set; }
        private int[] right { get; set; }
        private uint[] icod { get; set; }
        private uint[] setbit { get; set; } = new uint[32];

        /// <summary>
        /// Given the frequency of occurrence table nfreq[0..nnch - 1] for nnch charac-
        /// ters, constructs the Huffman code.Also sets ilong and nlong as the
        /// character number that produced the longest code symbol, and the length of
        /// that symbol.
        /// </summary>
        /// <param name="nnch"></param>
        /// <param name="nfreq"></param>
        /// <exception cref="Exception"></exception>
        public Huffcode(int nnch, int[] nfreq)
        {
            this.nch = nnch;
            this.mq = 2 * nch - 1;
            this.icod = new uint[mq];
            this.ncod = new int[mq];
            this.left = new int[mq];
            this.right = new int[mq];

            int[] index = new int[mq];
            int[] nprob = new int[mq];
            int[] up = new int[mq];
            for (int j = 0; j < 32; j++)
            {
                setbit[j] = (uint)(1 << j);
            }
            int nused = 0;
            for (int j = 0; j < nch; j++)
            {
                nprob[j] = nfreq[j];
                icod[j] = 0;
                ncod[j] = 0;
                if (nfreq[j] != 0)
                {
                    index[nused++] = j;
                }
            }
            for (int j = nused - 1; j >= 0; j--)
            {
                heep( index,  nprob, nused, j);
            }
            int k = nch;
            while (nused > 1)
            {
                int node = index[0];
                index[0] = index[(nused--) - 1];
                heep( index,  nprob, nused, 0);
                nprob[k] = nprob[index[0]] + nprob[node];
                left[k] = node;
                right[k++] = index[0];
                up[index[0]] = -(int)k;
                index[0] = k - 1;
                up[node] = k;
                heep( index,  nprob, nused, 0);
            }
            up[(nodemax = k) - 1] = 0;
            for (int j = 0; j < nch; j++)
            {
                if (nprob[j] != 0)
                {
                    int n = 0;
                    int ibit = 0;
                    for (int node = up[j]; node > 0; node = up[node - 1], ibit++)
                    {
                        if (node < 0)
                        {
                            n |= (int)setbit[ibit];
                            node = -node;
                        }
                    }
                    icod[j] = (uint)n;
                    ncod[j] = ibit;
                }
            }
            nlong = 0;
            for (int j = 0; j < nch; j++)
            {
                if (ncod[j] > nlong)
                {
                    nlong = ncod[j];
                    ilong = j;
                }
            }
            if (nlong > 16)// numeric_limits<uint>.digits)
            {
                throw new Exception("Code too long in Huffcode.  See text.");
            }
        }

        /// <summary>
        /// Huffman encode the single character ich(in the range 0..nch-1), write the
        /// result to the byte array code starting at bit nb(whose smallest valid
        /// value is zero), and increment nb to the first unused bit.This routine is
        /// called repeatedly to encode consecutive characters in a message. The user
        /// is responsible for monitoring that the value of nb does not overrun the
        /// length of code.
        /// </summary>
        /// <param name="ich"></param>
        /// <param name="code"></param>
        /// <param name="nb"></param>
        /// <exception cref="Exception"></exception>
        public void codeone(int ich, ref string code, ref int nb)
        {
            char[] cc = code.ToCharArray();

            if (ich >= nch)
            {
                throw new Exception("bad ich (out of range) in Huffcode");
            }
            if (ncod[ich] == 0)
            {
                throw new Exception("bad ich (zero prob) in Huffcode");
            }
            for (int n = ncod[ich] - 1; n >= 0; n--, ++nb)
            {
                int nc = nb >> 3;
                int m = nb & 7;
                if (m == 0)
                {
                    code = code.Substring(0, nc);
                }
                if ((icod[ich] & setbit[n]) != 0)
                {
                    //code[nc] |= setbit[m];
                    cc[nc] |= (char)setbit[m];
                }
            }

            code = new string(cc);
        }

        /// <summary>
        /// Starting at bit number nb in the byte array code, decode a single character
        /// (returned as ich in the range 0..nch-1) and increment nb appropriately.
        /// Repeated calls, starting with nb D 0, will return successive characters in
        /// a compressed message. The user is responsible for detecting EOM from the
        /// message content.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="nb"></param>
        /// <returns></returns>
        public int decodeone(ref string code, ref int nb)
        {
            int node = nodemax - 1;
            for (; ; )
            {
                int nc = nb >> 3;
                node = ((code[nc] & setbit[7 & nb++]) != 0 ? right[node] : left[node]);
                if (node < nch)
                {
                    return node;
                }
            }
        }

        /// <summary>
        /// Used by the constructor to maintain a heap structure in the array
        /// index[0..m - 1].
        /// </summary>
        /// <param name="index"></param>
        /// <param name="nprob"></param>
        /// <param name="n"></param>
        /// <param name="m"></param>
        public void heep(int[] index, int[] nprob, int n, int m)
        {
            int i = m;
            int k = index[i];
            int j;
            while (i < (n >> 1))
            {
                if ((j = 2 * i + 1) < n - 1 && nprob[index[j]] > nprob[index[j + 1]])
                {
                    j++;
                }
                if (nprob[k] <= nprob[index[j]])
                {
                    break;
                }
                index[i] = index[j];
                i = j;
            }
            index[i] = k;
        }
    }
}
 

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

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

相关文章

[LeetCode周赛复盘] 第 326 场周赛20230702

[LeetCode周赛复盘] 第 326 场周赛20230702 一、本周周赛总结6909. 最长奇偶子数组1. 题目描述2. 思路分析3. 代码实现 6916. 和等于目标值的质数对1. 题目描述2. 思路分析3. 代码实现 6911. 不间断子数组1. 题目描述2. 思路分析3. 代码实现 6894. 所有子数组中不平衡数字之和…

【小沐学Unity3d】Unity播放视频(VideoPlayer组件)

文章目录 1、简介2、脚本播放示例3、界面播放示例3.1 2d界面全屏播放3.2 2d界面部分区域播放3.3 3d模型表面播放 结语 1、简介 使用视频播放器组件可将视频文件附加到游戏对象&#xff0c;然后在运行时在游戏对象的纹理上播放。 视频播放器 (Video Player) 组件: 属性功能Sourc…

Java实现OpenAI 模型训练(fine-tune)

本文章介绍如何用java实现OpenAI模型训练&#xff0c;仅供参考 提前准备工作 OpenAI KEY&#xff0c;获取方式可自行百度需要自备VPN 或 使用国外服务器转发需要训练的数据集&#xff0c;文章格式要求为JSONL&#xff0c;格式内容详见下图&#xff08;尽量不要低于500个问答&…

openai

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;人工智能。 目录 1、简介2、如何实现3、api文档 1、简介 OpenAI 提供了一个名为 OpenAI API 的库&#xff0c;用…

npm构建vite项目

基础环境 npm init vitelatest 依次输入项目名称、使用框架、使用语言。 生成的项目 进入目录&#xff0c;安装依赖&#xff0c;启动项目。 cd 0702_demo01npm installnpm run dev

网络安全进阶学习第四课——SSRF服务器请求伪造

文章目录 一、什么是SSRF&#xff1f;二、SSRF成因三、SSRF简析四、PHP存在SSRF的风险函数五、后台源码获取方式六、SSRF危害七、SSRF漏洞挖掘从WEB功能上寻找&#xff0c;从URL关键字中寻找 八、SSRF具体利用ssrf常利用的相关协议PHP伪协议读取文件端口扫描 九、SSRF存在的必要…

架构分层方法指导

在《不过时的经典层架构》里讲了经典的四层架构怎样对易变性做封装。咱们实际项目中&#xff0c;如果没有足够的实践和关键性思考&#xff0c;还是很可能使用名义上科学的分类理论&#xff0c;却在按照功能进行架构分层。今天咱们就通过一些简单的指导来尽量减少这种风险。 四问…

LeetCode 75 —— 70. 爬楼梯

LeetCode 75 —— 70. 爬楼梯 一、题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法…

机器学习笔记 - 基于OpenCV和Vantage-point tree构建图像哈希搜索引擎

一、关于图像哈希 上一篇文章中,了解到了图像哈希是使用算法为图像分配唯一哈希值的过程。在深度学习普及之前,一些搜索引擎使用散列技术来索引图像。 言外之意目前的图像搜索引擎主要都是基于深度学习的技术,不过思路都是一样的,我们这里基于OpenCV提供的图像哈希技术构建…

python实现削苹果小游戏

也不用998只有199源码发你。 支付完发我邮箱发你源代码。

RISC-V处理器的设计与实现(三)—— 上板验证(基于野火征途Pro开发板)

文章目录 RISC-V处理器的设计与实现&#xff08;一&#xff09;—— 基本指令集_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&#xff08;二&#xff09;—— CPU框架设计_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&#xff08;三&#xff09;—— 上板验…

Gradle安装与配置(8.2)

一、下载地址 https://gradle.org/releases/ https://downloads.gradle.org/distributions/gradle-8.2-bin.zip 解压后放到合适的位置 二、配置环境变量并测试 D:\ProgramFiles\gradle-8.2\bin gradle -v 三、配置镜像 D:\ProgramFiles\gradle-8.2\init.d init.gradle&…

算法第36天:数组中出现次数超过一半的数字【摩尔投票法】

算法介绍 摩尔投票法&#xff1a;求众数的方法。 就是维护一个集合&#xff0c;然后我们遍历我们的数组&#xff0c;假如现在我们遍历到的数为x&#xff0c;当集合中都是x的话我们就将x放入集合中&#xff0c;如果我们遍历到的数为x&#xff0c;但是集合中有y&#xff0c;那么…

【VulnHub系列】West-Wlid1.1

实验信息 Kali&#xff1a;192.168.10.106 WestWild&#xff1a;192.168.104 实验过程 通过arp-scan查找目标主机&#xff0c;确定目标主机IP192.168.10.104 sudo arp-scan --interface eth0 192.168.10.0/24 探测靶机开放的端口 sudo nmap -sT --min-rate 10000 -p- 192.1…

Redis的持久化机制(1)

RDB&#xff0c;即Redis DataBase的简称。RDB是Redis默认的持久化机制 RDB持久化文件&#xff0c;速度比较快&#xff0c;而且存储的是一个二进制的文件&#xff0c;传输起来很方便 在指定的时间间隔内&#xff0c;将内存中的数据集的快照写入磁盘。默认保存在/usr/local/bin目…

122.【SpringBoot - 再刷 - 基础入门 - 01】

SpringBoot2 核心技术 (一)、SpringBoot核心技术入门1.Spring能做什么?1.1、Spring 的能力1.2、Spring的生态1.3、Spring5重大升级1.3.1、响应式编程1.3.2、内部源码设计 2.为什么用SpringBoot2.1、SpringBoot优点2.2、SpringBoot缺点 3.时代背景3.1、微服务3.2、分布式的困难…

github克隆代码加速

https://www.gitclone.com/gogs/ 只需要在正常的git clone后的URL里&#xff0c;嵌入gitclone.com即可快速clone 举例&#xff1a; #原地址 git clone https://github.com/SpringSource/Spring-framework #新地址 git clone https://gitclone.com/github.com/SpringSource/…

2023年出货量预计增长75%,谁在领跑规模化量产赛道?

2023年将成为一个分水岭&#xff0c;中国智能驾驶市场已经进入了下一个竞争周期&#xff0c;卷&#xff0c;难 成为了智驾赛道新的关键词&#xff0c;对各赛道的供应商来说&#xff0c;未来几年将是比拼规模化与降本。 对各级供应商来说&#xff0c;产品规模化量产&#xff0c…

【二叉树part07】| 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236.二叉树的最近公共祖先

目录 &#x1f388;LeetCode530.二叉搜索树的最小绝对差 &#x1f388;LeetCode501.二叉搜索树中的众数 &#x1f388;LeetCode236.二叉树的最近公共祖先 &#x1f388;LeetCode530.二叉搜索树的最小绝对差 链接&#xff1a;530.二叉树的最小绝对差 给你一个二叉搜索树的根…

主成分分析系列(二)为什么特征向量是主成分

在主成分分析系列&#xff08;一&#xff09;概览及数据为何要中心化这篇文章中介绍了PCA算法的大概想法及数据为何要中心化&#xff0c;在这篇文章具体推导PCA算法的过程。 1. 首先 PCA 最原始的想法是&#xff1a; 设 V \mathbf{V} V 为 d {d} d 维 线性空间&#xff08;即…