`
raidyue
  • 浏览: 18783 次
  • 性别: Icon_minigender_1
  • 来自: 湖南常德
社区版块
存档分类
最新评论

哈弗曼压缩

阅读更多

 

一、哈弗曼树,又称最优树,是一种带权路径长度最短的树。

路径长度:        两个节点之间的路径上的分支数目

数的带权路劲长度:树中所有叶子节点的带权路径长度之和(WPL值,其中WPL最小的就叫最优二叉树或者哈弗曼树)。

二、哈弗曼树的建立

哈弗曼树也算二叉树的一种,所以哈弗曼树的建立和二叉树类似,只是多了个参数--权值。

基本步骤:

一.读取文件,将读取的信息转化为ASCII码,建立数组以ASCII码为下标,记录字符出现的次数

二.生成节点,根据节点的权值排序(使用优先队列) 三.构建哈夫曼树,生成码表根据权值进行排序,根据权值排好序以后,去前两个节点也就是最小的节点,取出后删除节点,两个节点形成一个新的节点,权值小的为新节点的左子节点,权值大的为右子节点。(同时给节点赋值,左子节点为“0”,右子节点为“1”。这就是哈弗曼编码,我们在递归的时候让子节点不断加上父节点的哈弗曼编码就能得到该节点的哈弗曼编码。)我们再将新节点加入优先队列重复以上步骤

HuffmanNode node1 = nodeQueue.poll();

			HuffmanNode node2 = nodeQueue.poll();
			HuffmanNode parent_node = new HuffmanNode(0, node1.getCount()+ node2.getCount());
			parent_node.setLeftChild(node1);
			node1.setHuffmanCode("0");
			parent_node.setRightChild(node2);
			node2.setHuffmanCode("1");
			nodeQueue.add(parent_node);
 

三、得到哈弗曼编码

哈弗曼树构建好了以后我们开始遍历这棵树,得到他的哈弗曼编码,首先该节点的左右字数是否为空,是则得到其哈弗曼编码,反之则遍历,将子节点的编码加上父节点的编码

if (root.getLeftChild() == null && root.getRightChild() == null) {

			// 把叶子节点添加到节点数组里
			leafNode[counter] = root;
			counter++;
			
		} else {
			// 获取当前节点的哈夫曼编码值
			String str = root.getHuffmanCode();
			// 左节点的编码值加上当前节点的编码值
			str += root.getLeftChild().getHuffmanCode();
			// 把加后的编码值赋值给左节点
			root.getLeftChild().setHuffmanCode(str);
			// 递归左节点
			printHuffmanCode(root.getLeftChild());
			// 获取当前节点的编码值
			String str1 = root.getHuffmanCode();
			// 右节点的编码值加上当前节点的编码值
			str1 += root.getRightChild().getHuffmanCode();
			// 把加后的编码值赋值给右节点
			root.getRightChild().setHuffmanCode(str1);
			// 递归右节点
			printHuffmanCode(root.getRightChild());
		}
		
 

四、文件的写入

将所有的哈弗曼编码不够八位的补满八位,超过八位补成整数个八位,同时记录补零的个数

for (int i = 0; i < leafNode.length; i++) {

				allhfmCode[i] = leafNode[i].getHuffmanCode();
			}

			for (int i = 0; i < leafNode.length; i++) {
				int zeroCount = 0;
				String presentCode = leafNode[i].getHuffmanCode();
				while (presentCode.length() % 8 != 0) {
					zeroCount++;
					presentCode += "0";
				}
				int bytesize = presentCode.length() / 8;
				leafNode[i].setByteSize(bytesize);

				leafNode[i].setHuffmanCode(presentCode);

				leafNode[i].setZeroCount(zeroCount);

				allString += leafNode[i].getHuffmanCode();
			}
 

将头文件信息写完后,用一串字符进行标记,将头信息和文件体信息隔开解压文件时可以进行判断。文件写入时每八位写入,没有八位的补零满八,写入,同时写入补零个数

for (int i = 0; i < allString.length(); i++) {

				// 一个一个的读取给中转字符
				writes += allString.charAt(i);
				// 当读满八位时执行
				if (i % 8 == 7) {
					if (byteCount1 == byteCount2) {
						// 写入该字符占有几个位置
						byteCount2 = leafNode[nodeCount].getByteSize();
						bos.write(leafNode[nodeCount].getByteSize());
						// 写入字符
						bos.write(leafNode[nodeCount].getASCII());
						// 写入补了多少个0
						String str_zerocount = Integer.toString(leafNode[nodeCount]
								.getZeroCount());
						bos.write((int) str_zerocount.charAt(0));
						nodeCount++;
						byteCount1 = 0;
					}
					// 把这8位字符串转化成整形
					if (byteCount1 < byteCount2) {
						int x = ChangeString(writes);
						// 写入转换后的整型
						bos.write(x);
						// 中转字符串归零
						writes = "";
						byteCount1++;
					}
				}
			}
		
			for (int i = 0; i < 5; i++) {
				bos.write(97 + i);
			}
			// 定义计数器,记录的是内容的补零个数
			int zeroCount = 0;
			// 定义一个存储内容编码的字符串
			String content = "";
			// 定义一个中转字符串
			String tranString = "";
			// 遍历读取文件内容,并写入文件
			for (int i = 0; i < length; i++) {
				// 读取文件
				int x = bis.read();
				// 循环判断该字符所对应的编码
				for (int j = 0; j < allhfmCode.length; j++) {
					if (x == leafNode[j].getASCII()) {
						// 把编码赋值给字符串中存储
						content += allhfmCode[j];
					}
				}
				// 如果此时的字符串位数大于等于8
				if (content.length() >= 8) {
					// 循环获得前八位
					for (int j = 0; j < 8; j++) {
						tranString += content.charAt(j);
					}
					// 把这8位字符串转化成整形
					int a = ChangeString(tranString);
					// 写入转换后的整型
					bos.write(a);
					// 清空转换字符串
					tranString = "";
					// 循环获得除去前八位后剩下的字符
					for (int j = 8; j < content.length(); j++) {
						tranString += content.charAt(j);
					}
					// 把原先的字符串覆盖掉
					content = tranString;
					// 清空转换字符串
					tranString = "";
				}
			}
			// 如果没有满八位,则补上0
			while (content.length() % 8 != 0) {
				zeroCount++;
				content += "0";
			}
			// 把这8位字符串转化成整形
			if (content.equals("")) {
			} // 把这8位字符串转化成整形
			else {
				int b = ChangeString(content);
				// 写入转换后的整型
				bos.write(b);
			}
			// 写入补零计数器
			String so = Integer.toString(zeroCount);
			bos.write((int) so.charAt(0));
 

五、文件解压

解压可以算是压缩的逆过程

按照自己写入的规律读取文件形成新的文件

 

分享到:
评论

相关推荐

    哈弗曼压缩总结

    哈弗曼压缩是一种高效的数据压缩方法,主要基于哈弗曼树(Huffman Tree)的构建。这个技术在信息编码和数据存储中具有广泛的应用,特别是在文本压缩、图像压缩和文件传输等领域。以下是对哈弗曼压缩相关知识点的详细...

    哈弗曼压缩解压器.rar

    在哈弗曼压缩过程中,首先需要统计输入文本中各个字符的出现频率,然后构建哈弗曼树。构建过程通常采用贪心算法,通过不断地合并频率最小的两个节点来逐步形成完整的树形结构。最后,根据树的结构生成每个字符的...

    哈弗曼压缩解压算法代码.rar

    在哈弗曼压缩过程中,首先需要建立一个哈弗曼树。这通常包括以下步骤: 1. **统计字符频率**:对输入的数据流进行分析,统计每个字符出现的次数。 2. **构建哈弗曼树**:创建一个空的优先队列,将每个字符作为一个带...

    哈弗曼压缩代码1

    哈弗曼压缩编码

    哈弗曼压缩解压文件

    在Java环境中实现哈弗曼压缩与解压文件,主要涉及以下几个关键知识点: 1. **哈弗曼树的构建**:哈弗曼树是一种带权路径长度最短的二叉树,权重小的节点通常位于树的顶层。构建哈弗曼树通常使用优先队列(如Java中...

    自适应哈弗曼压缩编码VC源码

    这个"自适应哈弗曼压缩编码VC源码"是使用Visual Studio 2010开发的一个工程,它提供了实现自适应哈弗曼编码算法的C++源代码。VS2010是一个流行的集成开发环境(IDE),支持C++编程,提供了一整套工具,包括编译器、...

    以字母为基础的哈弗曼压缩

    在C语言实现哈弗曼压缩的过程中,首先需要做的是统计输入文本中每个字符的出现频率。这个过程通常涉及读取文本文件,计算每个字符的词频,并将这些信息存储在一个字典或数组中。在这个案例中,`词频表_Character.txt...

    哈弗曼压缩解压算法VC++源码示例

    哈弗曼编码(Huffman Coding)是一种数据压缩算法,由美国计算机科学家大卫·艾尔曼在1952年提出。...在实际项目中,哈弗曼压缩算法常用于文本、图像和其他类型数据的压缩,以节省存储空间和提高传输效率。

    huffman--MATLAB哈弗曼压缩纯英文文本+图像Huffman编码

    在给定的文件中,我们有两个文件:一个是关于MATLAB实现的哈弗曼压缩纯英文文本的程序,另一个是关于图像的哈弗曼编码。MATLAB是一种强大的编程环境,尤其适用于数值计算和算法开发,因此它是实现哈弗曼编码的理想...

    数据结构课程设计 哈弗曼压缩+纸牌游戏

    实现哈弗曼压缩及解压缩功能,并计算压缩前后文件占用空间比 模型建立与题目分析 压缩: 以二机制可读形式打开源文件,以二进制可写形式打开压缩目标文件。每次从源文件读取八个比特(一字节),作为一个ASCII码...

    数据结构哈弗曼压缩课设

    在这个“数据结构哈弗曼压缩课设”中,你需要理解和应用以下几个关键知识点: 1. ASCII码:ASCII码(American Standard Code for Information Interchange)是计算机中字符的一种标准编码方式,包括数字、字母和...

    huffmanCompress哈弗曼压缩与解压缩

    huffmanCompress哈弗曼压缩与解压缩,一个压缩工具

    哈弗曼压缩编码报告1

    ### 哈弗曼压缩编码知识点详解 #### 实验项目名称 - **哈夫曼编码/译码器** #### 实验目的 本实验的主要目的是实现一个哈夫曼编码与解码的过程,即对输入的字符串进行哈夫曼编码,再对编码后的字符串进行解码,...

    课程实习时做的哈弗曼压缩程序

    在这个“课程实习时做的哈弗曼压缩程序”中,我们可以推测作者尝试实现了哈弗曼编码的基本流程,包括以下几个步骤: 1. **频率统计**:首先,需要对输入的文本或数据流中的字符进行频率统计,了解每个字符出现的...

    哈弗曼压缩软件(数据结构试验报告附源程序).pdf

    《哈弗曼压缩软件》是基于数据结构课程设计的一个项目,主要目的是让学生将所学的哈弗曼编码理论知识应用于实际问题中,提高编程技能。哈弗曼编码是一种高效的无损数据压缩方法,通过构建最优的二叉树(哈弗曼树)来...

    哈弗曼压缩和解压以及多项式的运算

    哈弗曼压缩的过程包括以下步骤: 1. **构建哈弗曼树**:首先统计每个字符的出现频率,然后用这些频率作为权重创建一个优先队列。接着,每次从队列中取出两个权重最小的节点,合并成一个新的节点,新节点的权重为两子...

    哈弗曼压缩解压算法,VC 源代码下载.rar

    在VC(Visual C++)环境中实现哈弗曼压缩和解压,通常涉及到以下几个关键步骤: 1. **频率统计**:首先,我们需要对输入的数据流进行分析,统计每个字符出现的频率。这是构建哈弗曼树的基础。 2. **构建哈弗曼树**...

    哈弗曼压缩软件(数据结构试验报告附源程序).docx

    《哈弗曼压缩软件(数据结构试验报告附源程序).docx》的文件内容主要涉及一个数据结构课程设计项目,该项目是实现一个基于哈弗曼编码的文本压缩软件。哈弗曼编码是一种高效的前缀编码方法,常用于数据压缩,其原理是...

    哈弗曼 压缩原理

    ### 哈弗曼压缩原理详解 #### 引言 数据压缩技术自其诞生以来,一直是信息技术领域的重要组成部分,尤其在大数据和网络通信时代显得更为关键。哈弗曼压缩算法,由D.A. Huffman在1952年提出,是一种基于统计特性...

    哈弗曼压缩算法

    在哈弗曼压缩过程中,首先需要统计输入文本中每个字符的出现频率,生成一个频率表。然后,使用这些频率来构造一棵哈弗曼树,这是一个特殊的二叉树,其中每个叶子节点代表一个字符,而内部节点表示合并后的频率。构建...

Global site tag (gtag.js) - Google Analytics