Huffman 编码的编程与实现 C语言
一 、目的:
1. 掌握Huffman树的概念、存储结构;
2. 掌握建立Huffman树和Huffman编码的方法;
二 、环境:
operating system version:Win11
CPU instruction set: x64
Integrated Development Environment:Viusal Studio 2022
三 、内容:
利用动态分配数组存储赫夫曼树,设计一组输入数据(假定为一组整数),能够对其进行如下操作:
1)创建一个新的顺序表,实现动态空间分配的初始化
2)对输入的数据构造成一棵 Huffman 树;
3)根据生成的 Huffman 树进行 Huffman 编码
4)实现对输入数据的 Huffman 编码输出 。
四 、要求:
1) 实现 Huffman 树的生成
2) 完成 Huffman 编码的输出 。
五 、步骤:
1. 程序:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h> using namespace std;
typedef char ElemType;
typedef struct { ElemType elem; unsigned int weight; unsigned int parent, lchild, rchild, tag;
}HTNode, * HuffmanTree;
typedef char** HuffmanCode; typedef int Status;
typedef struct weight
{ char elem; unsigned int m_weight;
}Weight; void Select(HuffmanTree HT, int n, int& s1, int& s2)
{ int i; s1 = s2 = 0; for (i = 1; i <= n; i++) { if (HT[i].weight < HT[s2].weight && HT[i].parent == 0 && s2 != 0) { if (HT[i].weight < HT[s1].weight) { s2 = s1; s1 = i; } else s2 = i; } if ((s1 == 0 || s2 == 0) && HT[i].parent == 0) { if (s1 == 0) s1 = i; else if (s2 == 0) { if (HT[i].weight < HT[s1].weight) { s2 = s1; s1 = i; } else s2 = i; } } } if (s1 > s2) { i = s1; s1 = s2; s2 = i; }
} void HuffmanCoding(HuffmanTree& HT, HuffmanCode& HC, Weight*& w, int n) { // w存放n个字符的权值(均>0),构造哈夫曼树HT, // 并求出n个字符的哈夫曼编码HC //本函数实现选择方式:从左往右选择两个小权值结点,结点信息在前面的为左子树,其后为右子树 int i, j, m, s1, s2; char* cd; int p; int cdlen; if (n <= 1) return; m = 2 * n - 1; HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); // 0号单元未用 for (i = 1; i <= n; i++) { //初始化 HT[i].elem = w[i - 1].elem; HT[i].weight = w[i - 1].m_weight; HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0; } for (i = n + 1; i <= m; i++) { //初始化 HT[i].weight = 0; HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0; } printf("\n哈夫曼树的构造过程如下所示:\n"); printf("HT初态:\n 结点 weight parent lchild rchild"); for (i=1; i<=m; i++) printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight, HT[i].parent,HT[i].lchild, HT[i].rchild); getchar(); for (i = n + 1; i <= m; i++) { // 建哈夫曼树 // 在HT[1..i-1]中选择parent为0且weight最小的两个结点, // 其序号分别为s1和s2。 Select(HT, i - 1, s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lchild = s1; HT[i].rchild = s2; HT[i].weight = HT[s1].weight + HT[s2].weight; printf("\nselect: s1=%d s2=%d\n", s1, s2); printf(" 结点 weight parent lchild rchild"); for (j=1; j<=i; j++) printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight, HT[j].parent,HT[j].lchild, HT[j].rchild); getchar(); } //------无栈非递归遍历哈夫曼树,求哈夫曼编码 HC = (HuffmanCode)malloc((n + 1) * sizeof(char*)); cd = (char*)malloc((n + 1) * sizeof(char)); // 分配求编码的工作空间 p = m; cdlen = 0; for (i = 1; i <= m; ++i) // 遍历哈夫曼树时用作结点状态标志 HT[i].tag = 0; while (p) { if (HT[p].tag == 0) { // 向左 HT[p].tag = 1; if (HT[p].lchild != 0) { p = HT[p].lchild; cd[cdlen++] = '0'; } else if (HT[p].rchild == 0) { HC[p] = (char*)malloc((cdlen + 1) * sizeof(char)); cd[cdlen] = '\0'; strcpy(HC[p], cd); } } else if (HT[p].tag == 1) { // 向右 HT[p].tag = 2; if (HT[p].rchild != 0) { p = HT[p].rchild; cd[cdlen++] = '1'; } } else { // HT[p].weight==2,退回退到父结点,编码长度减1 HT[p].tag = 0; p = HT[p].parent; --cdlen; } }
} void OutputHuffmanCode(HuffmanTree HT, HuffmanCode HC, int n)
{ int i; printf("\nnumber---element---weight---huffman code\n"); for (i = 1; i <= n; i++) printf(" %d %c %d %s\n", i, HT[i].elem, HT[i].weight, HC[i]);
} int main()
{ HuffmanTree HT; HuffmanCode HC; Weight* w; char c; // the symbolizes; int i, n; // the number of elements; int wei; // the weight of a element; printf("请输入准备构建哈夫曼树的结点数:"); cin >> n; //cout<<endl; w = (Weight*)malloc(n * sizeof(Weight)); for (i = 0; i < n; i++) { printf("请输入结点编号与对应的权值(node weight):"); scanf("%1s%d", &c, &wei); w[i].elem = c; w[i].m_weight = wei; } HuffmanCoding(HT, HC, w, n); OutputHuffmanCode(HT, HC, n); }
2.程序结果:
1)程序运行,我使用的测试数据如下所示:
2)首先按照要求完成了哈夫曼树的构建:
3)最终完成哈夫曼编码,结果与预期一致。
六 、小结:
此次是关于哈夫曼树的编程与实现,通常给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
我先输入了权值的 n 个结点,并且在构建哈夫曼树时我采用了如下办法:首先在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的二叉树,且新二叉树的根结点的权值为左右孩子权值的和;在原有的 n 个权值中删除那两个最小的权值,同时将新的权值加入到 n–2 个权值的行列中,以此类推;重复上述过程,直到所以的结点构建成了一棵二叉树为止,就得到了哈夫曼树。通常查找权重值最小的两个结点的思想是:从树组起始位置开始,首先找到两个无父结点的结点(说明还未使用其构建成树),然后和后续无父结点的结点依次做比较,有两种情况需要考虑:如果比两个结点中较小的那个还小,就保留这个结点,删除原来较大的结点;如果介于两个结点权重值之间,替换原来较大的结点。最终实现了描述的功能。
Huffman 编码的编程与实现 C语言相关推荐
- HuffMan编码C语言实现
HuffMan编码C语言实现 实现了一种编码方式,和两种解码方式. 解码一种使用的是叶子回溯根. 一种使用了从根遍历过程. 代码: HuffManEncoding // // Created by Z ...
- huffman编码压缩c语言,用Huffman编码对文件进行压缩的C语言实现
本文介绍了采用Huffman编码对ASCII码文件进行压缩的基本原理,并用C语言程序实现了这个压缩过程.文中给出了比较完整的C语言程序代码,可以直接用于调试实验. 福 建电 脑 21 0 2年第 1期 ...
- huffman编码译码器用c语言,基于哈弗曼编码的数据压缩C语言实现
haod 摘要 数据压缩技术是一项重要实用的信息技术.信息时代的到来,信息量迅速增长,使得数据压缩也显得越来越重要.数据压缩有多种编码方法,大致可分为无损压缩编码和有损压缩编码.其中,Huffman ...
- Huffman 编码的实现(C语言)
Huffman 编码 具体原理及定义请百度,下面直接进行实现.具体实现过程是: 统计若干字符出现的频率,将其按频率(权重)升序存放进队列中,每次从队列中取两个结点合成一颗二叉树,这两个结点的根节点是取 ...
- 基于Huffman编码的C语言解压缩文件程序
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h>//极大 ...
- 数据压缩实验三:用c语言实现Huffman编码和压缩效率分析
实验原理: 1.Huffman编码 Huffman编码是一种无失真的编码方式,是可变字长编码(VLC)的一种. Huffman编码基于信源的概率统计模型,它的基本思路是: 出现概率大的信源符号编长码, ...
- Huffman编码的C语言实现
实验原理 Huffman 编码 (1) Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman 编码是可变字长编码(VLC)的一种. (2)Huffman 编码基于信源 ...
- 霍夫曼(Huffman)编码算法详解之C语言版
一.Huffman编码 霍夫曼(Huffman)树是一类带权路径长度最短的二叉树树.Huffman树的一个非常重要的应用就是进行Huffman编码以得到0-1码流进行快速传输. 在电报收发等数据通讯中 ...
- huffman图像编码C语言,Huffman编码 数据结构 C语言
为解决广大童鞋的数据结构实验问题写下本文:(只做参考哦.) 实验要求: Huffman编码(二叉树) l实验目的:熟练掌握二叉树应用(Huffman编码)的基本算法实现. l实现功能:对输入的一串电文 ...
最新文章
- Hadoop学习之MapReduce(一)
- 使用Docker中的mysql
- mallcloud商城基于SpringBoot2.x
- 9.5noip模拟试题
- 鸿蒙安卓生态已经非常完善,鸿蒙前进一小步,生态却完善一大步,解决了替换安卓的第一个问题...
- qqxml图片代码_分享三款高级qqxml消息卡片代码
- 微信小程序- MQTT模拟器
- 安装打印机时出现无法安装,打印处理器不存在
- 软件测试入门知识,Linux系统基础教程——带你玩转Linux(五)
- Ubuntu 18.04 LTS上编译安装BCC
- Nova8pro自动调节亮度忽亮忽暗问题
- 什么是可视化?数据可视化有什么作用和价值
- 地震了!最好直接砸死我!
- python爬取百度迁徙动态图_爬取动态图片—以百度图片为例
- 2021国产数据库领域最具商业合作价值企业盘点
- STM32MP157系列教程连载-Linux应用开发篇1:STM32MP1微处理器之Ubuntu安装与体验
- 哲学家进餐_我如何通过预算学习计划进餐
- 软件测试常用术语总结
- 上拉电阻和下拉电阻判断
- [python]编写程序产生 ISBN 号的校验位。