数据压缩 实验三 Huffman编解码算法实现与压缩效率分析

huffman编解码算法实验与压缩效率分析 一、基本原理 1、huffman编码原理 huffman编码是一种无失真编码方式,是可变长(VLC)编码的一种。 huffman编码基于信源的概率统计模型,基本思路是出现概率大的信源符号编长码,出现概率小的符号编短码,从而使平均码长最小。 2、数据结构 在本实验中的数据结构中,用到了两个数据结构: 在程序实现过程中,使用了一种二叉树的数据结构,由它编出的码是即时码。树是一种重要的非线性 阅读详情

实验目的

掌握Huffman编解码实现的数据结构和实现框架, 进一步熟练使用C编程语言, 并完成压缩效率的分析。

实验原理

1.本实验中Huffman编码算法
(1)将文件以ASCII字符流的形式读入,统计每个符号的发生频率;
(2)将所有文件中出现过的字符按照频率从小到大的顺序排列;
(3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较;
(4)重复3,直到最后得到和为1的根节点;
(5)将形成的二叉树的左节点标0,右节点标1,把从最上面的根节点到最下面的叶子节点途中遇到的0、1序列串起来,得到了各个字符的编码表示。
2.Huffman编码的数据结构设计
在程序实现中使用一种叫做二叉树的数据结构实现Huffman编码。
(1)哈夫曼节点结构
typedef struct huffman_node_tag
{
unsigned char isLeaf; //是否为树叶
unsigned long count; //节点代表的符号加权和
struct huffman_node_tag *parent; //父节点指针
union
{
struct
{
struct huffman_node_tag *zero, *one; //子节点指针,分别代表0,1子节点指针
};
unsigned char symbol; //节点代表的符号
};
} huffman_node;
(2)哈夫曼码结构
typedef struct huffman_code_tag
{
unsigned long numbits; //该码所用的比特数
unsigned char *bits; //指向该码比特串的指针
} huffman_code;
3.本实验中Huffman编码的流程

代码分析

实验中将实际完成编码工作的工程Huff_code封装成一个静态链接库,由工程huff_run来调用,huff_run完成的工作包括解析命令行参数,打开、读取、关闭输入文件,打开关闭输出文件,调用Huff_code完成编码。

Huff_run
huffcode.c

#include "huffman.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>

#ifdef WIN32
#include <malloc.h>
extern int getopt(int, char**, char*);
extern char* optarg;
#else
#include <unistd.h>
#endif

static int memory_encode_file(FILE *in, FILE *out);
static int memory_decode_file(FILE *in, FILE *out);

static void version(FILE *out)
{
    fputs("huffcode 0.3\n"
          "Copyright (C) 2003 Douglas Ryan Richardson"
          "; Gauss Interprise, Inc\n",
          out);
}

static void usage(FILE* out)
{
    fputs("Usage: huffcode [-i<input file>] [-o<output file>] [-d|-c]\n"
          "-i - input file (default is standard input)\n"
          "-o - output file (default is standard output)\n"
          "-d - decompress\n"
          "-c - compress (default)\n"
          "-m - read file into memory, compress, then write to file (not default)\n"
          "-t - output huffman statistics\n",
          out);
}

int main(int argc, char** argv)
{
    char memory = 0;
    char compress = 1;
    int opt;
    const char *file_in = NULL, *file_out = NULL;
    const char *file_out_table = NULL;
    FILE *in = stdin;
    FILE *out = stdout;
    FILE * outTable = NULL;

    /* Get the command line arguments. */
    while((opt = getopt(argc, argv, "i:o:cdhvmt:")) != -1) //演示如何跳出循环,及查找括号对
    {
        switch(opt)
        {
        case 'i':
            file_in = optarg;
            break;
        case 'o':
            file_out = optarg;
            break;
        case 'c':
            compress = 1;
            break;
        case 'd':
            compress = 0;
            break;
        case 'h':
            usage(stdout);
            return 0;
        case 'v':
            version(stdout);
            return 0;
        case 'm':
            memory = 1;
            break;
        case 't':
            file_out_table = optarg;            
            break;
        default:
            usage(stderr);
            return 1;
        }
    }

    /* If an input file is given then open it. */
    if(file_in)
    {
        in = fopen(file_in, "rb");
        if(!in)
        {
            fprintf(stderr,
                    "Can't open input file '%s': %s\n",
                    file_in, strerror(errno));
            return 1;
        }
    }

    /* If an output file is given then create it. */
    if(file_out)
    {
        out = fopen(file_out, "wb");
        if(!out)
        {
            fprintf(stderr,
                    "Can't open output file '%s': %s\n",
                    file_out, strerror(errno));
            return 1;
        }
    }

    if(file_out_table)
    {
        outTable = fopen(file_out_table, "w");
        if(!outTable)
        {
            fprintf(stderr,
                "Can't open output file '%s': %s\n",
                file_out_table, strerror(errno));
            return 1;
        }
    }

    if(memory)
    {
        return compress ?
            memory_encode_file(in, out) : memory_decode_file(in, out);
    }

    if(compress)
        huffman_encode_file(in, out,outTable);
    else
        huffman_decode_file(in, out);

    if(in)
        fclose(in);
    if(out)
        fclose(out);
    if(outTable)
        fclose(outTable);
    return 0;
}

static int memory_encode_file(FILE *in, FILE *out)
{
    unsigned char *buf = NULL, *bufout = NULL;
    unsigned int len = 0, cur = 0, inc = 1024, bufoutlen = 0;

    assert(in && out);

    /* Read the file into memory. */
    while(!feof(in))
    {
        unsigned char *tmp;
        len += inc;
        tmp = (unsigned char*)realloc(buf, len);
        if(!tmp)
        {
            if(buf)
                free(buf);
            return 1;
        }

        buf = tmp;
        cur += fread(buf + cur, 1, inc, in);
    }

    if(!buf)
        return 1;

    /* Encode the memory. */
    if(huffman_encode_memory(buf, cur, &bufout, &bufoutlen))
    {
        free(buf);
        return 1;
    }

    free(buf);

    /* Write the memory to the file. */
    if(fwrite(bufout, 1, bufoutlen, out) != bufoutlen)
    {
        free(bufout);
        return 1;
    }

    free(bufout);

    return 0;
}

static int memory_decode_file(FILE *in, FILE *out)
{
    unsigned char *buf = NULL, *bufout = NULL;
    unsigned int len = 0, cur = 0, inc = 1024, bufoutlen = 0;
    assert(in && out);

    /* Read the file into memory. */
    while(!feof(in))
    {
        unsigned char *tmp;
        len += inc;
        tmp = (unsigned char*)realloc(buf, len);
        if(!tmp)
        {
            if(buf)
                free(buf);
            return 1;
        }

        buf = tmp;
        cur += fread(buf + cur, 1, inc, in);
    }

    if(!buf)
        return 1;

    /* Decode the memory. */
    if(huffman_decode_memory(buf, cur, &bufout, &bufoutlen))
    {
        free(buf);
        return 1;
    }

    free(buf);

    /* Write the memory to the file. */
    if(fwrite(bufout, 1, bufoutlen, out) != bufoutlen)
    {
        free(bufout);
        return 1;
    }

    free(bufout);

    return 0;
}

getopt.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* declarations to provide consistent linkage */
extern char *optarg;
extern int optind;
extern int opterr;

int opterr = 1,     /* if error message should be printed */
    optind = 1,     /* index into parent argv vector */
    optopt,         /* character checked for validity */
    optreset;       /* reset getopt */
char    *optarg;    /* argument associated with option */

#define BADCH   (int)'?'
#define BADARG  (int)':'
#define EMSG    ""

/*
 *  getopt --
 *  Parse argc/argv argument vector.
 */
int
getopt(int nargc, char * const *nargv, const char* ostr)
{
    static char *place = EMSG;      /* option letter processing */
    char *oli;              /* option letter list index */

    if (optreset || !*place) {      /* update scanning pointer */
        optreset = 0;
        if (optind >= nargc || *(place = nargv[optind]) != '-') {
            place = EMSG;
            return (EOF);
        }
        if (place[1] && *++place == '-') {  /* found "--" */
            ++optind;
            place = EMSG;
            return (EOF);
        }
    }                   /* option letter okay? */
    if ((optopt = (int)*place++) == (int)':' ||
        !(oli = strchr(ostr, optopt))) {
        /*
         * if the user didn't specify '-' as an option,
         * assume it means EOF.
         */
        if (optopt == (int)'-')
            return (EOF);
        if (!*place)
            ++optind;
        if (opterr && *ostr != ':')
            (void)fprintf(stderr,
                "%s: illegal option -- %c\n", __FILE__, optopt);
        return (BADCH);
    }
    if (*++oli != ':') {            /* don't need argument */
        optarg = NULL;
        if (!*place)
            ++optind;
    }
    else {                  /* need an argument */
        if (*place)         /* no white space */
            optarg = place;
        else if (nargc <= ++optind) {   /* no arg */
            place = EMSG;
            if (*ostr == 
Huffman 编解码算法实现与压缩效率分析 一、Huffman编解码原理 1 熵,又称为“信息熵” (Entropy)      1.1 在信息论中,熵是信息的度量单位。信息论的创始人 Shannon 在其著作《通信的 数学理论》中提出了建立在       概率统计模型上的信息度量。他把信息定义为“用来 消除不确定性的东西”。      1.2 一般用符号 H 表示,单位是比特。对于任意一个随机变量 X,它的熵定义如下: 阅读详情

相关推荐

实验三 Huffman编解码算法实现与压缩效率分析

一、Huffman编解码原理

GemRuswj的博客 1396

《数据压缩》实验报告三·Huffman编解码算法实现与压缩效率分析

一、实验原理  哈夫曼编码(Huffman Coding),又称霍夫曼编码或最佳码,是可变字长编码(VLC)的一种,属于无损压缩。该方法完全依据字符出现概率来构造码字,出现概率大的符号码长短,概率小的码长大,能有效的减小码长,对于概率分布相差大的信源压缩效率高,而对于接近于等概分布的信源压缩效率低。  实际实现中常用二叉树来表示编码过程,节点需要表示的信息有它的概率;它是否为叶子节点,不是

ininw的博客 1587

数据压缩原理 实验三 Huffman编解码算法实现与压缩效率分析

数据压缩原理 实验三 Huffman编解码算法实现与压缩效率分析

liu_yuchang的博客 853

数据压缩试验三 Huffman 编解码算法实现与压缩效率分析

掌握Huffman编解码实现的数据结构和实现框架, 进一步熟练使用C编程语言, 并完成压缩效率的分析。

Alfred512的博客 1095

数据压缩实验三:LZW 编解码算法实现与分析

②LZW算法的限制③LZW编码的应用 2.bitio.c 3.lzw.c 三、实验过程 1.首先调试LZW的编码程序,以一个文本文件作为输入,得到输出的LZW编码文件。 原始文件:命令行参数设置(编码):编码后: 命令行参数设置(解码):解码后: 其中txt、wav、yuv、xls文件压缩后文件大小变小,其余六个文件经压缩后反而变大。上述实验印证了LZW算法的特点:字符串重复度低时,压缩效率下降,这是因为不重复的字符串需要更多空间存储词典,导致文件变大。因此,文件本身重复的字符串越

weixin_46723979的博客 821

数据压缩实验三——霍夫曼编解码算法实现

Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman编码是可变字长编码(VLC)的一种。 Huffman 编码基于信源的概率统计模型,它的基本思路是,出现概率大的信源符号编长码,出现概率小的信源符号编短码,从而使平均码长最小。 在程序实现中常使用一种叫做树的数据结构实现Huffman编码,由它编出的码是即时码

willshant的博客 1659

数据压缩实验三:Huffman编解码

一、基本原理 1.Huffman编码算法 ()统计频率:将文件以ASCII字符流的形式读入,统计每个符号的发生频率; (2)排序:将所有文件中出现过的字符按照频率从小到大的顺序排列; (3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较;重复此步骤,直到最后得到和为1的根节点; (4)编码:将形成的二叉树的左节点标0

namino_的博客 560

【数据压缩】Huffman编解码器

一.实验原理1.Huffman编码1)Huffman Coding(霍夫曼编码)是一种无失真编码的编码方式,Huffman编码是可编长编码(VLC)的一种。 2)Huffman编码基于信源的概率统计模型,它的基本思路是:出现概率大的信源符号编短码,出现概率小的编长码。从而实现平均码长最小。 3)在程序实现中常使用一种叫做树的数据结构实现Huffman编码,由它编出的码是即时码。2.Huffm

caidejun的博客 997

图像的Huffman编码

图像的Huffman编码 有注释 希望对大家有用!!!!

一步步教你获取ADNI影像数据:从搜索到下载全流程解析

本文详细解析了从ADNI数据库获取阿尔茨海默病影像数据的全流程,包括账号注册、数据检索技巧、高效下载策略及常见问题解决方案。特别介绍了高级搜索的黄金组合和智能数据集管理方法,帮助研究者快速获取T1加权MRI、PET等多模态影像数据,提升科研效率。

weixin_29061465的博客 323

Selenium ChromeDriver反爬与性能优化实战指南

ChromeDriver作为Selenium的核心驱动,本质是浏览器自动化执行引擎,其默认行为会暴露大量JS运行时指纹(如navigator.webdriver、window.chrome),极易被前端反爬系统识别;同时因进程管理粗放、渲染等待机制僵化,导致内存泄漏、僵尸进程和高并发下稳定性崩塌。本文围绕真实生产场景,系统解析浏览器指纹伪造原理、进程级资源管控策略、基于页面状态的智能等待范式,并提供Docker容器化、K8s弹性扩缩与Prometheus可观测性落地路径,助力开发者将ChromeDriver

weixin_29762151的博客 1259

基于Simulink的直流电机双闭环调速系统抗扰动仿真与参数优化

本文详细介绍了基于Simulink的直流电机双闭环调速系统仿真与参数优化方法。通过构建转速外环与电流内环的仿真模型,阐述了利用工程设计法整定PI参数的核心步骤,并重点探讨了如何优化系统参数以增强其抗负载突变等扰动的能力,实现快速、平稳的调速性能。

weixin_29061997的博客 193

Gromacs实战:从蛋白质-小分子对接到分子动力学模拟全流程解析

本文详细解析了使用Gromacs进行蛋白质-小分子对接和分子动力学模拟的全流程,包括文件准备、拓扑生成、复合物构建、溶剂化处理、能量最小化及平衡模拟等关键步骤。通过实战案例,帮助研究者验证药物分子与靶标蛋白的结合稳定性,提升分子动力学模拟的效率和准确性。

weixin_29216353的博客 380

AI大模型与碳足迹评估结合模式及示范案例

AI大模型与碳足迹评估相结合,可以提供更精确、更快速的碳排放量计算,优化减排策略,并促进可持续发展目标的实现。

贾贾的博客 3943

ABB机器人与西门子PLC、工业相机联合实现无序抓取的完整调试方案

将此方案导入系统后,逐步执行调试,确保各环节信号正常触发,即可实现高效无序抓取!

CHUXUEZHE8210的博客 1993

把 SAP Event Mesh 讲透:从事件驱动架构到 SAP BTP 落地实践

摘要: SAP Event Mesh是SAP BTP上的云端消息与事件服务,支持企业构建解耦、弹性的应用架构。它通过异步通信模式(如发布/订阅)解决传统同步集成的痛点,如系统紧耦合、链路脆弱等问题。核心能力包括事件驱动通信、可靠消息投递(支持至少一次送达)、与SAP生态深度集成(如S/4HANA事件扩展)以及混合环境支持。典型场景包括订单处理、库存同步等,发布方只需发出业务事件,订阅方按需消费,避免系统间直接依赖,符合Clean Core理念。两种关键模式为广播式的Publish/Subscribe和定向的

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 116

配置 SAP ABAP Secure Storage

系统在进行数据加密时,会将数据与当前 Key ID 进行关联,也就是说,如果此时使用的是 Key ID 4713,则该条数据会在 Encrypt.Data 字段存储一个由密钥 4713 加密后的密文。Key ID 代表了不同的密钥标识,Current Key 表示系统当前正在使用的主密钥,Value 则是对应密钥的存储值,Management Data 通常包括一些管理性或辅助性的信息,用于描述密钥的状态、过期时间或者其他属性。对于每一条被加密的业务数据,系统会记录它使用了哪一条 Key ID。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 565

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: 数据压缩 实验二 图像文件的读写和转换
下一篇: 数据压缩 实验四 DPCM压缩系统的实现和分析
MayNine
博客等级 码龄10年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值