哈夫曼编/译码器

本文介绍了一个基于C语言实现的哈夫曼编/译码系统,包括初始化、编码、解码、打印代码文件和哈夫曼树的功能。系统通过读取字符集大小及权重,构建哈夫曼树并进行文件的编码与解码,提高信道利用率。
摘要由CSDN通过智能技术生成

哈夫曼编/译码器

一、需求分析

1. 问题阐述

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。

2. 基本要求

一个完整的系统应具有以下功能:
(1)I:初始化(initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding)。利用已建好的哈夫曼树(如不在内容,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrint中。
(5)T:印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

二、概要设计

  1. 数据存储:
    a) 结构体hfmNode :存储哈夫曼树中的结点数据:
    b) 二维动态字符数组HuffmanCode:存储所有字符的哈夫曼编码:
    c) 整型变量n:存储字符集大小,即字符总数
    d) 动态整形数组w:存储所有字符的权重
    e) 动态字符数组ch:存储所有字符
  2. 具体功能:
    a) Menu()函数:以菜单形式打印用户界面
    b) Select()函数:查找哈夫曼树中权重之和最小的两个结点
    c) HuffmanCoding()函数:建立哈夫曼树,并求哈夫曼编码
    d) Init()函数:初始化。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中
    e) Encoding()函数:编码。利用已建好的哈夫曼树(如不在内容,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中
    f) Decoding()函数:解码。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
    g) Printing()函数:打印代码文件。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrint中
    h) TreePrinting()函数:将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

三、详细设计

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

typedef struct hfmNode
{
   
    char ch;                    // 字符
    int weight;                 // 权重
    int parent, lchild, rchild; // 指向双亲、孩子结点的指针
} HTNode, *HuffmanTree;

typedef char **HuffmanCode; // 动态分配数组存储哈夫曼编码表

void Menu();                                                                   // 菜单
void Select(HuffmanTree HT, int end, int *s1, int *s2);                        // 查找哈夫曼树中权重和最小的两个结点
void HuffmanCoding(HuffmanTree *HT, HuffmanCode *HC, int n, int *w, char *ch); // 建立哈夫曼树
void Init(HuffmanTree *HT, HuffmanCode *HC, int *n, int *w, char *ch);         // 初始化                                                       // 初始化
void Encoding(HuffmanTree *HT, HuffmanCode *HC, int *n, int *w, char *ch);     // 编码                                                        // 编码
void Decoding(HuffmanTree *HT, HuffmanCode *HC, int *n, int *w, char *ch);     // 译码                                                        // 译码
void Printing();                                                               // 打印代码文件
void TreePrinting(HuffmanTree HT, int root, int type, int level);              // 打印哈夫曼树                                                                  // 释放动态分配空间

int main(void)
{
   
    int n = 0;       // 字符集大小
    int *w = NULL;   // 存储字符权重的数组
    char *ch = NULL; // 存储字符的数组
    char operation;  // 操作码
    HuffmanTree HT;  // 哈夫曼树
    HuffmanCode HC;  // 存储哈夫曼编码的数组

    while (1)
    {
   
        Menu();
        printf("Please input the operation: ");
        scanf("%c", &operation);
        getchar();
        switch (operation)
        {
   
        case 'i':
        case 'I':
            Init(&HT, &HC, &n, w, ch);
            break;
        case 'e':
        case 'E':
            Encoding(&HT, &HC, &n, w, ch);
            break;
        case 'd':
        case 'D':
            Decoding(&HT, &HC, &n, w, ch);
            break;
        case 'p':
        case 'P':
            Printing();
            break;
        case 't':
        case 'T':
            TreePrinting(HT, 2 * n - 1, 0, 0);
            break;
        case 'q':
        case 'Q':
            exit(0);
            break;
        default:
            break;
        }
    }
    return 0;
}

// 菜单
void Menu()
{
   
    printf("\n-------------------------------\n");
    printf("#                             #\n");
    printf("#      I: Initialization      #\n");
    printf("#      E: Encoding            #\n");
    printf("#      D: Decoding            #\n");
    printf("#      P: Printing            #\n");
    printf("#      T: Tree Printing       #\n")
  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
[ 问题描述 ] 利用哈夫曼编码进行信息通讯可以大大提高信道利用率, 缩短信息传输时间,降低传输成本。但是, 这要求在发送端通过一个码系统对待传数据预先码; 在接收端将传来的数据进行译码( 复原 )。对于双工信道( 即可以双向传输信息的信道 ), 每端都需要一个完整的/译码系统。试为这样的信息收发站写一个哈夫曼码的译码系统。 [ 基本要求 ] 一个完整的系统应具有以下功能: (1) I:初始化(Initialization)。从终端读入字符集大小 n,及 n 个字符和 n 个权值,建立哈夫曼树, 并将它存于文件 hfmtree 中。 (2) C:码(Coding)。利用已建好的哈夫曼树(如不在内存, 则从文件 hfmtree 中读入), 对文件 tobetrans 中的正文进行码, 然后将结果存入 codefile 中。 (3) D:译码(Decoding)。利用已建好的哈夫曼树将文件 codefile 中的代码进行译码, 结果存入文件 textfile 中。 (4) P:印代码文件(Print)。将文件 codefile 以紧凑格式显示在终端上, 每行 50 个代码。同时将此字符形式的码文件写入文件 codeprint 中。 (5) T:印哈夫曼树(Tree print)。将已在内存中的哈夫曼树以直观的方式( 树或凹入表行式 )显示在终端上, 同时将此字符形式的哈夫曼树写入文件 treeprint 中。 [ 测试数据 ] (1)利用教科书 6-2 中的数据调试程序。 (2)用下表中给出的字符集和频度的实际统计数据建立哈夫曼树, 并实现以下报 文的码和译码: "THIS PROGRAM IS MY FAVORITE". 字符 A B C D E F G H I J 频度 186 64 13 22 32 103 21 15 47 57 1 字符 K L M N O P Q R S T U 频度 5 32 20 57 63 15 1 48 51 80 23 字符 V W X Y Z 频度 8 18 1 16 1 [ 实现提示 ] (1) 文件 codefile 的基类型可以设为子界型 bit=0..1。 (2) 用户界面可以设计为"菜单"方式: 显示上述功能符号, 再加上"E",表示结束运行 End, 请用户键入一个选择功能符。此功能执行完毕后再显示此菜单, 直至某次用户选择了 "E"为止。 (3) 在程序的一次执行过程中, 第一次执行 I,D 或 C 命令之后, 哈符曼树已经在内存了, 不必再读入。每次执行中不一定执行 I 命令, 因为文件 hfmtree 可能早己建好。 [ 选作内容 ] (1) 上述 codefile 的基类型实际上占用了存放一个整数的空间, 只起到示意或模拟的作用。现使 codefile 的基类型 package=integer, 把哈夫曼码紧缩到一个整型变量中去, 最大限度地利用码点存储能力, 试改写你的系统。 (2) 修改你的系统, 实现对你的系统的源程序的码和译码。( 主要是将行尾符/译码问题 ) (3) 实现各个转换操作的源/目文件, 均由用户在选择此操作时指定。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zeekCheung

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值