目录

问题描述

基本要求

问题分析

实验代码

运行结果

实验总结


问题描述

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

基本要求

(1)接收原始数据(电文):从终端输入电文(电文为一个字符串,假设仅由26个小写英文字母构成)。

(2)编码:利用已建好的哈夫曼树,对电文进行编码。

(3)打印编码规则:即字符与编码的一一对应关系。

(4)打印显示电文以及该电文对应的哈夫曼编码。

(5)接收原始数据(哈夫曼编码):从终端输入一串哈二进制哈夫曼编码(由

0和1构成)。

(6)译码:利用已建好的哈夫曼树对该二进制编码进行译码。

(7)打印译码内容:将译码结果显示在终端上。

问题分析

(一)算法设计思路:

(1)接收原始数据:从Huffm.txt读入字符及其对应权值,建立哈夫曼树。

字符

-

A

B

C

D

E

F

G

H

I

J

K

L

M

频度

186

64

13

22

32

103

21

15

47

57

1

5

32

20

字符

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

频度

57

63

15

1

48

51

80

23

8

18

1

16

1

(2)编码:利用建好的哈夫曼树进行编码,存入HuffCode中,输入字符串,输出相应的密文。

(3)译码:利用已建好的哈夫曼树,将密文解码,输出对应明文。

(4)打印编码规则:字符与编码一一对应。

(二)使用模块及变量的说明

(1)typedef struct HNodeType:定义叶子结点。

(2)typedef struct HNodeType HFMTree[2*HUFFCODE-1]:建立储存哈夫曼树的数组。

(3)typedef struct HCodeType:定义储存编码的结点

(4)HCodeType HuffCode[HUFFCODE]:建立编码的数组

(5)void Creat_HuffMTree(HNodeType HFMTree[],int n):构造哈夫曼树

(6)void HaffmanCode(HNodeType HFMTree[], HCodeType HuffCode[],int n):哈夫曼编码过程,左分支是0,右分支是1

(7)void print_HuffCode(HCodeType HuffCode[]):打印编码规则

(8)void code_Huff(HCodeType HuffCode[],string s):编码过程,将字符串进行编码并输出对应二进制数

(9)void decode_Huff(string s, HNodeType HFMTree[], int n):译码过程,将二进制数使用哈夫曼树进行译码

实验代码

C++版

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#define HUFFCODE 27  //27个字符
#define MAXVALUE 10000 //构造哈夫曼树时使用//定义叶子结点
typedef struct {char data;int weight;int parent, lchild, rchild;
}HNodeType;
HNodeType HFMTree[2*HUFFCODE-1];//结构数组储存各字符编码
typedef struct {char data;    //每个结点储存字符int bit[HUFFCODE];   int start;
}HCodeType;
HCodeType HuffCode[HUFFCODE];//储存编码的数组//构造哈夫曼树
void Creat_HuffMTree(HNodeType HFMTree[],int n) {  int m1, x1, m2, x2;  //x1,x2存储最小和次小权值,m1,m2存储其位置int i, j;for (int i = 0; i < 2 * n - 1; i++) {  //HFMTree初始化HFMTree[i].weight = 0;     HFMTree[i].parent = -1;HFMTree[i].lchild = -1;        HFMTree[i].rchild = -1;}HFMTree[0].data = '_'; HFMTree[0].weight = 186;//设置空格(改为_了)的权值ifstream myfile("Huffm.txt");for (int i = 1; i < n; i++) {   myfile >> HFMTree[i].data;myfile >> HFMTree[i].weight;}myfile.close();for (int i = 0; i < n - 1; i++) {  //构造哈夫曼树x1 = x2 = MAXVALUE;m1 = m2 = 0;for (int j = 0; j < n + i; j++) {  //找出根结点具有最小和次小权值的两棵树if (HFMTree[j].parent == -1 && HFMTree[j].weight < x1) {x2 = x1; m2 = m1;x1 = HFMTree[j].weight; m1 = j;}else if (HFMTree[j].parent == -1 && HFMTree[j].weight < x2) {x2 = HFMTree[j].weight; m2 = j;}}HFMTree[m1].parent = n + i; HFMTree[m2].parent = n + i;//合并两棵树HFMTree[n + i].weight = HFMTree[m1].weight + HFMTree[m2].weight;HFMTree[n + i].lchild = m1; HFMTree[n + i].rchild = m2;}
}//哈夫曼编码过程,左分支是0,右分支是1
void HaffmanCode(HNodeType HFMTree[], HCodeType HuffCode[],int n) {HCodeType cd;    //字符编码的缓冲变量int i, j, c, p;for (i = 0; i < n; i++) {  //求每个叶子结点的哈夫曼编码cd.start = n - 1;c = i;p = HFMTree[c].parent;cd.data = HFMTree[c].data;while (p != -1) {if (HFMTree[p].lchild == c) cd.bit[cd.start] = 0;else cd.bit[cd.start] = 1;cd.start--;c = p;p = HFMTree[c].parent;}for (j = cd.start + 1; j < n; j++) {  //保存求出的每个叶结点的哈夫曼编码和编码的起始位置HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start + 1;HuffCode[i].data = cd.data;}
}//打印编码规则
void print_HuffCode(HCodeType HuffCode[]) {for (int i = 0; i < HUFFCODE; i++) {cout << HuffCode[i].data<<"对应编码:";for (int j = HuffCode[i].start; j < HUFFCODE; j++) {cout << HuffCode[i].bit[j];}cout << endl;}
}//编码过程,将字符串进行编码并输出对应二进制数
void code_Huff(HCodeType HuffCode[],string s) {int i = 0;ofstream outfile("textfile.txt");while (s[i] != '\0') {for (int j = 0; j < HUFFCODE; j++) { //遍历HuffCodeif (s[i] == HuffCode[j].data) {for (int k = HuffCode[j].start; k < HUFFCODE; k++) {cout << HuffCode[j].bit[k];}i++;break;}}}cout << endl;
}//译码过程,将二进制数使用哈夫曼树进行译码
void decode_Huff(string s, HNodeType HFMTree[], int n) {int i = 0, j = 0, p = 2 * n - 2;char a[1000] = {};while (s[i] != '\0') {if (s[i] == '0') {p = HFMTree[p].lchild;}else if (s[i] == '1') {p = HFMTree[p].rchild;}                //判断p是否为叶子结点,是则将对应数据储存进aif (HFMTree[p].lchild == -1 && HFMTree[p].rchild == -1) {a[j] = HFMTree[p].data; j++;p = 2 * n - 2;}else if (s[i + 1] == '\0' && HFMTree[p].lchild != -1 && HFMTree[p].rchild != -1) {cout << "译码失败!" << endl;return;}i++;}int k = 0;while (a[k]!=0 ) cout << a[k++];cout << endl;
}int menu() {int a;cout << "请选择功能键:";cin >> a;if (a >= 0 && a <= 3)    return a;else return -1;
}int main() {int a;string s1, s2;Creat_HuffMTree(HFMTree, HUFFCODE);HaffmanCode(HFMTree, HuffCode, HUFFCODE);cout << "********************" << endl;cout << "1.编码" << endl;cout << "2.译码" << endl;cout << "3.打印编码规则" << endl;cout << "0.退出" << endl;cout << "********************" << endl;a = menu();while (a != 0) {switch (a) {case 1:cout << "请输入要进行编码的明文:";cin >> s1;code_Huff(HuffCode, s1);    //进行编码a = menu();break;case 2:cout << "请输入要进行解码的密文:";cin >> s2;decode_Huff(s2, HFMTree, HUFFCODE);    //进行译码a = menu();break;case 3:cout << "编码规则为:" << endl;print_HuffCode(HuffCode);a = menu();break;case -1:cout << "请输入正确的功能键!" << endl;a = menu();break;}      }cout << "退出成功!" << endl;system("pause");return 0;
}

运行结果

实验总结

1、构造哈夫曼树时,从Huffm.txt读入字符及对应权值,需要使用fstream库。构造过程中数组下标没有处理好,导致出现各种问题。

2、译码过程用字符数组储存结果,若译码失败则不输出。这个过程最开始使用的是一个字符串变量储存,出现错误,程序无法运行,改用字符数组储存,并进行初始化,就解决了问题。

数据结构实验——哈夫曼编码相关推荐

  1. 【数据结构】哈夫曼编码与最优二叉树(哈夫曼树)

    一.为什么要用哈夫曼编码 在进行大容量存储.图像压缩等数据交换的时候,如果文件过大,恰好WIFI又不怎么快,你是不是会觉得十分暴躁呀?比如有这样一串数据需要传输: 上面就有100位二进制数,这还只是数 ...

  2. 霍夫曼编码PHP,数据结构:哈夫曼编码(php版)

    概述下: 哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,"哈夫曼编码"是一种一致性编码法(又称"熵编码法"),用于 ...

  3. 数据结构之哈夫曼编码

    例题: 假设一个文本文件TFile中只包含7个字符{A,B,C,D,E,F,G},这7个字符在文本中出现的次数为{5,24,7,17,34,5,13} 利用哈夫曼树可以为文件TFile构造出符合前缀编 ...

  4. 【数据结构】哈夫曼编码和树

    新知识: 转载博客:http://blog.163.com/sdnu_et/blog/static/13184636920100574953335/ 哈夫曼树:建一棵树,使每个叶子节点的点权与深度的乘 ...

  5. 数据结构实验之二叉树六:哈夫曼编码

    Description 字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码.该方法完全依据字符出现概率来构造出平均长度最短 ...

  6. sdut 数据结构实验之二叉树六:哈夫曼编码

    #include <iostream> #include <cstdio> #include <cstring> #include <queue>usi ...

  7. 数据结构“基于哈夫曼树的数据压缩算法”的实验报告

    一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055@qq.com Last edited: 2022.11.20 目录 数据结构& ...

  8. 数据结构哈夫曼编码解码课程设计

    数据结构课程设计 源代码在另一篇博客可以找到:https://blog.csdn.net/qq_40513633/article/details/85055411?ops_request_misc=% ...

  9. 蓝桥哈夫曼树C语言,实验四 哈夫曼树及哈夫曼编码

    实验目的## 掌握哈夫曼树的概念.哈夫曼编码及其应用. 掌握生成哈夫曼树的算法. 会用哈夫曼树对传输报文进行编码. 掌握二叉树的二叉链表存储方式及相应操作的实现. ##实验内容## 用哈夫曼编码进行通 ...

最新文章

  1. python操作手机京东_Python实现自动上京东抢手机
  2. MySQL索引如何优化?二十条铁则送你!!!
  3. 2. 托管对象数据模型的基本知识(Core Data 应用程序实践指南)
  4. C++prims算法生成最小协议树(附完整源码)
  5. get_called_class与get_class
  6. jmeter之-用Firefox录制https协议证书问题
  7. LWIP之UDP协议
  8. winafl 源码分析
  9. 定做属于自己的Lodop安装程序
  10. 如何使用初始化列表消除冗余C++代码
  11. 拼多多店铺等级怎么提升?店盈通来告诉你
  12. html css绘制24色环图,HTML5 色环钟表
  13. markdown编辑器推荐(附官网)
  14. 活动回顾|Derek做客Staking Mondays
  15. 软件开发人员如何自我学习?
  16. JS监听鼠标滑轮事件
  17. 拓扑结构计算机网络结构,计算机网络的常见的七种拓扑结构
  18. 雅思听力常见人名及地名(常考,必备)
  19. 关于旅游景点主题的HTML网页设计——青岛民俗 7页 带登录注册
  20. MySQL面试题和答案

热门文章

  1. opencv imread函数
  2. matlab中乘法“*”和点乘“.*”;除法“/”和点除“./”的联系和区别。
  3. echarts之 数据可视化简单页面模板
  4. 了解一下,Android 10 Build系统
  5. line-height行高
  6. 【软件测试】黑盒测试技术——等价类划分和边界值分析
  7. Linux 根目录与路径
  8. linux 命令行获取时间,【Linux】让命令提示符显示日期和时间
  9. java通过输入的方式给int数组赋值并输出数组
  10. 我的世界服务器拔刀修复,我的世界拔刀剑怎么修复武器攻略分享