`

哈夫曼树(哈夫曼建树及编码)

阅读更多

哈夫曼树是数据结构的一种,用于实现无损压缩。压缩分为无损压缩和有损压缩,使用哈夫曼压缩的压缩比可达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.把编码转成二进制串,存入文件中,即可实现压缩。

 

  • 大小: 5.9 KB
  • 大小: 185.3 KB
分享到:
评论

相关推荐

    哈夫曼树编码

    哈夫曼树编码是一种高效的前缀编码方法,广泛应用于数据压缩领域。它的基本思想是根据字符出现的频率来构建一棵特殊的二叉树——哈夫曼树(也称为最优二叉树),并以此来生成编码。这种方法能确保频繁出现的字符具有...

    哈夫曼树建立及编码,可在VC++6.0上运行

    ### 哈夫曼树建立及编码 #### 一、哈夫曼树简介 哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的二叉树,在数据压缩编码领域有着广泛的应用。哈夫曼树是由David A. Huffman于1952年提出的,其...

    哈夫曼树编码解码.c

    该文件是关于用C语言构建哈夫曼树的代码,其中包括对字符的统计、对文档读取然后包括建树的过程,和对哈夫曼树解码的过程。

    哈夫曼树c++代码 总共有4 个

    在本压缩包中,包含四个与哈夫曼树相关的C++代码,可能是用于构建、编码和解码的实现。 哈夫曼编码的基本原理是为每个字符分配一个唯一的二进制码,使得频率高的字符具有较短的编码,频率低的字符具有较长的编码。...

    哈夫曼树的应用数据结构课程设计.doc

    数据压缩是指使用哈夫曼树将数据压缩到最小的大小,信息Theory是指使用哈夫曼树对信息进行编码和译码。 四、实现哈夫曼树算法 哈夫曼树算法的实现步骤如下: * 首先,构建哈夫曼树的节点结构,包括节点的值、左...

    哈夫曼数及其编码

    1.掌握哈夫曼树的建树原理 2. 掌握哈夫曼树与哈夫曼码逻辑结构和存储结构。 3.掌握哈夫曼树与哈夫曼码的基本操作。 二、设计内容和要求 1.输入一个文本,统计各字符出现的频度,输出结果 2.使用二叉链表或三叉链表...

    哈夫曼树HuffmanTree

    `huffmanTree.h`文件可能定义了哈夫曼树的节点类以及相关的辅助函数,如插入节点到优先队列、构建哈夫曼树、生成和输出编码等。 哈夫曼树算法的关键在于它的效率:由于每次都是合并频率最小的两个节点,所以构建...

    哈夫曼数及其编码原理.

    1.掌握哈夫曼树的建树原理 2. 掌握哈夫曼树与哈夫曼码逻辑结构和存储结构。 3.掌握哈夫曼树与哈夫曼码的基本操作。 二、设计内容和要求 1.输入一个文本,统计各字符出现的频度,输出结果 2.使用二叉链表或三叉链表...

    运用哈夫曼编码压缩解压文件源代码

    * 哈夫曼树的构建:需要根据字符的频率信息构建哈夫曼树,确保高频率的符号用短的编码表示。 * 编码长度:需要根据哈夫曼树的结构确定每个字符的编码长度。 * 压缩效率:需要根据实际情况选择合适的压缩算法和参数,...

    哈夫曼编码译码器

    2. **建树模块**:构建哈夫曼树的实现。 3. **编/译码模块**:实现字符串的编码和解码。 在实现过程中,还需要注意错误处理,例如用户输入的合法性检查,以及在选择错误功能时给出相应的提示。此外,为了提高程序的...

    Java基础复习笔记09数据结构-哈夫曼树

    哈夫曼编码是一种基于哈夫曼树的前缀编码方式,可以有效减少数据的存储空间。哈夫曼编码的基本思想是:用0和1的组合来表示字符,其中出现频率高的字符使用较短的编码,出现频率低的字符使用较长的编码。具体而言,...

    哈夫曼树的压缩程序及其效果

    压缩文件通常会包含文件头信息,如文件名、原始文件长度以及哈夫曼树的节点信息,以便在解压缩时重建树结构。在解压缩过程中,需要从压缩文件中读取这些信息,然后根据哈夫曼树的结构解析位流,将编码转换回原始字符...

    java实现哈夫曼算法

    在哈夫曼编码过程中,首先构建一个哈夫曼树,这个树是一个特殊的二叉树,具有以下特点:叶子节点代表要编码的字符,非叶子节点的权重是其子节点权重之和,且左子树的权重小于右子树的权重。 【Java实现哈夫曼编码】...

    C语言课程设计哈夫曼编译码建树

    哈夫曼编码是一种广泛应用于数据压缩领域的编码方式,其主要特点是通过对原始数据进行统计分析后,构建一颗特殊的二叉树(即哈夫曼树),从而为不同的字符或符号分配长度不等的编码。这种编码方法能够有效减少数据的...

    哈夫曼编码

    然而,由于编码过程需要构建哈夫曼树,因此在处理大量数据时,建树的时间成本不容忽视。 在你的课程设计中,你可能会使用编程语言实现上述过程,例如使用Python或C++。你可能需要编写函数来生成哈夫曼树,生成编码...

    哈夫曼编码 matalb

    它通过构建最优的二叉树(也称为哈夫曼树或最优权值树)来为每个输入符号分配一个唯一的前缀编码,使得频繁出现的字符具有较短的编码,不频繁的字符则具有较长的编码,从而实现对数据的高效压缩。在MATLAB环境中,...

    哈夫曼编码译码器.doc

    在哈夫曼编码译码器中,我们使用二叉排序树来存储编码结果。二叉排序树是一种特殊的二叉树,每个节点的值都小于或等于其右子树中的所有节点的值。我们使用中序遍历来遍历二叉排序树,从而输出编码结果。 4. 程序...

    哈夫曼编/译码器代码

    1) 对指定的文本文件进行各字符出现频度分析,并建立哈夫曼树与哈夫曼编码,将该文本文件编码成目标文件 也可另输入字符和对应频度建树 2) 对已编码的文件进行解码,还原成原来的文件

    数据结构课设

    - **哈夫曼树类**:实现哈夫曼树的构建及相关操作。 - **编码类**:执行编码操作。 - **译码类**:执行译码操作。 - **计算压缩比类**:计算压缩前后的大小比例。 ##### 3. 详细设计与实现 **界面类** - 使用标准...

    课程设计 - 数据结构 -112,113,115班题目要求

    1. **掌握哈夫曼树的建树原理**:理解哈夫曼树的构造过程。 2. **掌握哈夫曼树与哈夫曼编码逻辑结构和存储结构**:了解哈夫曼树的数据结构特点。 3. **掌握哈夫曼树与哈夫曼编码的基本操作**:熟练使用哈夫曼树进行...

Global site tag (gtag.js) - Google Analytics