哈夫曼树是数据结构的一种,用于实现无损压缩。压缩分为无损压缩和有损压缩,使用哈夫曼压缩的压缩比可达3:1到5:1,流行的有损压缩方法有lzw字典压缩等。
几个名词解释:
最优二叉树:树的加权路径总长度最短的二叉树。
权值:每个叶子节点带有一定的权值,在哈夫曼树中为该叶子节点代表的字符的出现频率。
树的加权路径总长度:各叶子节点到根节点的路径长度与该节点的权的乘积的总和。
加权路径长度:从根节点到该节点之间的路径长度与该节点的权的乘积。
路径长度(深度):当前节点到根节点所经历的层数。
叶子节点:没有子树的节点。
根节点:没有父节点的节点。
哈夫曼树属于二叉树的一种,是一种非线性的数据结构,其实现压缩的思想大致如下:
举个例子:英文中各个字母出现的频率是大不相同的,因此,对不同字母的编码长度若相同,就会浪费太多的空间,若给予出现频率较高的字符以较短的编码,而出现频率较少的字符以较长的编码。那么,总体的编码长度便会大大缩短,把该二进制编码存进文件中可实现压缩。术语志之曰:“最优编码方法”。哈夫曼树是一种最优二叉树,其自下向上的建树方法使得权值越大的节点越靠近根节点。
实现过程:
1.统计字符频率
建一个大小为256的byte数组,使用位映射,每读入一个字节,便在数组中该字节对应的ASCII码对应的位置加一,这样一来,文件读完的时候,字符频率也就统计完了。如:读入字符a,便使byte数组的下标为97的元素加一。
//统计字符频率 private byte[] bytecount = new byte[256]; public void countWeight() throws IOException { java.io.InputStream fins = new java.io.FileInputStream( "D:/JAVA/TestForIO(java)/testforIO.txt"); while (fins.available() > 0) { int i = fins.read();// 读入字节 bytecount[i]++;// 统计每个字节出现的次数(位图映射) } fins.close(); }
2.建树
i.使用队列,把字符及其频率存到一个队列中。
ii.对队列按频率大小进行排序,取频率最小的两个节点,生成一个父节点,权值为两个节点的频率之和,然后把这两个元素从队列中删掉,把父节点存到队列中。然后又排序,生成······如此往复,直到队列中只剩下一个节点,该节点就是根节点。
/* * 使用队列构建哈夫曼树 */ private static HuffNode root;// 声明根节点 public void creatHuffTree() { ArrayList<HuffNode> quene = new ArrayList<HuffNode>();// 创建队列,使用指定排序规则 // 把所有节点加入队列中 for (int i = 0; i < bytecount.length; i++) { if (bytecount[i] != 0) { // System.out.println(((char) i) + " " + bytecount[i]); HuffNode node = new HuffNode((char) i, bytecount[i]); quene.add(node);// 加入节点 } } // 构建哈夫曼树 while (quene.size() != 1) { sort(quene); HuffNode min1 = quene.get(0);// 获取队列头两个 quene.remove(0); HuffNode min2 = quene.get(0); quene.remove(0); HuffNode result = new HuffNode('-', min1.times + min2.times); result.leftchild = min1; result.rightchild = min2; quene.add(result); } // 得到根节点 root = quene.get(0); System.out.println("root=" + root.data + " " + root.times); }
3.编码
哈夫曼树建成后,对其进行编码,左边子树编码为0,右边为1。
// (前序遍历) private Code[] saveCode = new Code[256];// 创建一个code数组,储存每个字符对应的编码和编码长度 public void getMB(HuffNode root, String s) { if (root.leftchild == null && root.rightchild == null) { Code huffcode = new Code(); huffcode.length = s.length();// 把编码串的长度存到huffcode的length属性中 huffcode.code = s;// 把编码串存到huffcode的code属性中 saveCode[root.data] = huffcode;// 把huffcode对象存进saveCode对象数组中 System.out.println("节点" + root.data + "编码" + huffcode.code); System.out.println("节点" + root.data + "次数" + huffcode.length); } // 左0右1 if (root.leftchild != null) { getMB(root.leftchild, s + "0"); } if (root.rightchild != null) { getMB(root.rightchild, s + "1"); } }
为便于理解,建树及编码过程如图所示(图片来自维基百科):
各字符频率如下:
建树过程:
4.把编码转成二进制串,存入文件中,即可实现压缩。
相关推荐
哈夫曼树编码是一种高效的前缀编码方法,广泛应用于数据压缩领域。它的基本思想是根据字符出现的频率来构建一棵特殊的二叉树——哈夫曼树(也称为最优二叉树),并以此来生成编码。这种方法能确保频繁出现的字符具有...
### 哈夫曼树建立及编码 #### 一、哈夫曼树简介 哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的二叉树,在数据压缩编码领域有着广泛的应用。哈夫曼树是由David A. Huffman于1952年提出的,其...
该文件是关于用C语言构建哈夫曼树的代码,其中包括对字符的统计、对文档读取然后包括建树的过程,和对哈夫曼树解码的过程。
在本压缩包中,包含四个与哈夫曼树相关的C++代码,可能是用于构建、编码和解码的实现。 哈夫曼编码的基本原理是为每个字符分配一个唯一的二进制码,使得频率高的字符具有较短的编码,频率低的字符具有较长的编码。...
数据压缩是指使用哈夫曼树将数据压缩到最小的大小,信息Theory是指使用哈夫曼树对信息进行编码和译码。 四、实现哈夫曼树算法 哈夫曼树算法的实现步骤如下: * 首先,构建哈夫曼树的节点结构,包括节点的值、左...
1.掌握哈夫曼树的建树原理 2. 掌握哈夫曼树与哈夫曼码逻辑结构和存储结构。 3.掌握哈夫曼树与哈夫曼码的基本操作。 二、设计内容和要求 1.输入一个文本,统计各字符出现的频度,输出结果 2.使用二叉链表或三叉链表...
`huffmanTree.h`文件可能定义了哈夫曼树的节点类以及相关的辅助函数,如插入节点到优先队列、构建哈夫曼树、生成和输出编码等。 哈夫曼树算法的关键在于它的效率:由于每次都是合并频率最小的两个节点,所以构建...
1.掌握哈夫曼树的建树原理 2. 掌握哈夫曼树与哈夫曼码逻辑结构和存储结构。 3.掌握哈夫曼树与哈夫曼码的基本操作。 二、设计内容和要求 1.输入一个文本,统计各字符出现的频度,输出结果 2.使用二叉链表或三叉链表...
* 哈夫曼树的构建:需要根据字符的频率信息构建哈夫曼树,确保高频率的符号用短的编码表示。 * 编码长度:需要根据哈夫曼树的结构确定每个字符的编码长度。 * 压缩效率:需要根据实际情况选择合适的压缩算法和参数,...
2. **建树模块**:构建哈夫曼树的实现。 3. **编/译码模块**:实现字符串的编码和解码。 在实现过程中,还需要注意错误处理,例如用户输入的合法性检查,以及在选择错误功能时给出相应的提示。此外,为了提高程序的...
哈夫曼编码是一种基于哈夫曼树的前缀编码方式,可以有效减少数据的存储空间。哈夫曼编码的基本思想是:用0和1的组合来表示字符,其中出现频率高的字符使用较短的编码,出现频率低的字符使用较长的编码。具体而言,...
压缩文件通常会包含文件头信息,如文件名、原始文件长度以及哈夫曼树的节点信息,以便在解压缩时重建树结构。在解压缩过程中,需要从压缩文件中读取这些信息,然后根据哈夫曼树的结构解析位流,将编码转换回原始字符...
在哈夫曼编码过程中,首先构建一个哈夫曼树,这个树是一个特殊的二叉树,具有以下特点:叶子节点代表要编码的字符,非叶子节点的权重是其子节点权重之和,且左子树的权重小于右子树的权重。 【Java实现哈夫曼编码】...
哈夫曼编码是一种广泛应用于数据压缩领域的编码方式,其主要特点是通过对原始数据进行统计分析后,构建一颗特殊的二叉树(即哈夫曼树),从而为不同的字符或符号分配长度不等的编码。这种编码方法能够有效减少数据的...
然而,由于编码过程需要构建哈夫曼树,因此在处理大量数据时,建树的时间成本不容忽视。 在你的课程设计中,你可能会使用编程语言实现上述过程,例如使用Python或C++。你可能需要编写函数来生成哈夫曼树,生成编码...
它通过构建最优的二叉树(也称为哈夫曼树或最优权值树)来为每个输入符号分配一个唯一的前缀编码,使得频繁出现的字符具有较短的编码,不频繁的字符则具有较长的编码,从而实现对数据的高效压缩。在MATLAB环境中,...
在哈夫曼编码译码器中,我们使用二叉排序树来存储编码结果。二叉排序树是一种特殊的二叉树,每个节点的值都小于或等于其右子树中的所有节点的值。我们使用中序遍历来遍历二叉排序树,从而输出编码结果。 4. 程序...
1) 对指定的文本文件进行各字符出现频度分析,并建立哈夫曼树与哈夫曼编码,将该文本文件编码成目标文件 也可另输入字符和对应频度建树 2) 对已编码的文件进行解码,还原成原来的文件
- **哈夫曼树类**:实现哈夫曼树的构建及相关操作。 - **编码类**:执行编码操作。 - **译码类**:执行译码操作。 - **计算压缩比类**:计算压缩前后的大小比例。 ##### 3. 详细设计与实现 **界面类** - 使用标准...
1. **掌握哈夫曼树的建树原理**:理解哈夫曼树的构造过程。 2. **掌握哈夫曼树与哈夫曼编码逻辑结构和存储结构**:了解哈夫曼树的数据结构特点。 3. **掌握哈夫曼树与哈夫曼编码的基本操作**:熟练使用哈夫曼树进行...