Java学习第28天:Huffman编码(节点定义与文件读取)

 

 

关于Huffman编码相关定义可以看相关链接:https://blog.csdn.net/Kprogram/article/details/81052982

 Huffman树可以根据输入的字符串中某个字符出现的次数来给某个字符设定一个权值,然后可以根据权值的大小给一个给定的字符串编码,或者对一串编码进行解码,可以用于数据压缩或者解压缩,和对字符的编解码。 

基本概念:

Huffman树:给定带权的N个叶子构成的所有二叉树中,树的带权路径长度最小的二叉树(最优二叉树)

带权路径长度:所有树叶到树根之间的路径长度与该节点上权的乘积

权:赋予节点的有意义的参数

赫夫曼树的构造:

 例:设权值集合{2,4,5,7}

 

    1.根据权值进行排序,取最小的两个叶子(2,4),较小的在左,较大的在右。添加一个新节点,节点的权值为它俩的权值和,构成一颗二叉树:

 

  2.用得到的节点作为新的叶子,重复第一步:

  3.一直重复构造,直到所有子叶都取完

 

 所以共需要进行n-1次构造,总共有 n+n-1 = 2n -1 个节点;可以证明,这样构造的二叉树是带权路径长度最小的二叉树。

赫夫曼编码:

1.数据压缩(编码):把文件中的每个字符转换成一个唯一的二进制位串,且串里面不能包含其它字符的表示串。

2.赫夫曼编码方法:如上例,设权为字符在文档中的重复次数,权值集合为{A:2,B:4,C:5,D:7},从根节点开始,向左是0,向右是1。

那么A的编码为:110;B的编码为:111;C的编码为:10;D的编码为:0。
 

 

主要任务:今天主要是将Huffman中的一些元素定义出来,同时将目标文件的读取也实现出来。

package day28;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Collectors;

public class Huffman {
	/**
	 * An inner class for Huffman nodes.
	 */
	class HuffmanNode {
		/**
		 * 字符,仅对叶节点有效.
		 */
		char character;

		/**
		 * 权值.
		 */
		int weight;

		/**
		 * 左孩子.
		 */
		HuffmanNode leftChild;

		/**
		 * 右孩子.
		 */
		HuffmanNode rightChild;

		/**
		 * 父节点,其作用主要是用来组合哈夫曼节点 .
		 */
		HuffmanNode parent;

		/**
		 ******************* 
		 * The first constructor
		 ******************* 
		 */
		public HuffmanNode(char paraCharacter, int paraWeight, HuffmanNode paraLeftChild,
				HuffmanNode paraRightChild, HuffmanNode paraParent) {
			character = paraCharacter;
			weight = paraWeight;
			leftChild = paraLeftChild;
			rightChild = paraRightChild;
			parent = paraParent;
		}// Of HuffmanNode

		/**
		 ******************* 
		 * To string.
		 ******************* 
		 */
		public String toString() {
			String resultString = "(" + character + ", " + weight + ")";

			return resultString;
		}// Of toString

	}// Of class HuffmanNode

	/**
	 * 面向的数据限制为ASCLL.
	 */
	public static final int NUM_CHARS = 256;

	/**
	 *储存字符串.
	 */
	String inputText;

	/**
	 * 字符串长度,同时也是叶节点的数量.
	 */
	int alphabetLength;

	/**
	 * 储存出现过的字符.
	 */
	char[] alphabet;

	/**
	 * 所有节点数量,2*n-1,n为叶节点数量.
	 */
	int[] charCounts;

	/**
	 * 字符到字母表中索引的映射.
	 */
	int[] charMapping;

	/**
	 * 将字符映射为Huffman编码.
	 */
	String[] huffmanCodes;

	/**
	 * 储存所有节点,最后一个为根节点.
	 */
	HuffmanNode[] nodes;

	/**
	 *********************
	 * The first constructor.
	 * 
	 * @param paraFilename
	 *            The text filename.
	 *********************
	 */
	public Huffman(String paraFilename) {
		charMapping = new int[NUM_CHARS];

		readText(paraFilename);
	}// Of the first constructor

	/**
	 *********************
	 * 读取文件.
	 * 
	 * @param paraFilename
	 *            The text filename.
	 *********************
	 */
	public void readText(String paraFilename) {
		try {
			inputText = Files.newBufferedReader(Paths.get(paraFilename), StandardCharsets.UTF_8)
					.lines().collect(Collectors.joining("\n"));
		} catch (Exception ee) {
			System.out.println(ee);
			System.exit(0);
		} // Of try

		System.out.println("The text is:\r\n" + inputText);
	}// Of readText

注:基本原理都如上。理解完原理再看程序就相对简单了。

下面转自闵老师:每个节点的内容包括: 字符 (仅对叶节点有效)、权重 (用的整数, 该字符的个数)、指向子节点父节点的引用. 这里指向父节点的引用是必须的.NUM_CHARS 是指 ASCII 字符集的字符个数. 为方便起见, 仅支持 ASCII.inputText 的引入只是想把程序尽可能细分成独立的模块, 这样便于学习和调拭.alphabet 仅存 inputText 出现过的字符.alphabetLength 完全可以用alphabet.length() 代替,.charCounts 要为所有的节点负责, 其元素对应于 HuffmanNode 里面的 weight. 为了节约, 可以把其中一个省掉.charMapping 是为了从 ASCII 里面的顺序映射到 alphabet 里面的顺序. 这也是我只采用 ASCII 字符集 (仅 256 字符) 的原因.huffmanCodes 将个字符映射为一个字符串, 其实应该是二进制串. nodes 要先把所有的节点存储在一个数组里面, 然后再链接它们. 这是常用招数.构造方法仅初始化了 charMapping, 读入了文件.readText 采用了最简单粗暴的方式. 还可以有其它的逐行读入的方式.要自己弄个文本文件, 里面存放一个字符串 abcdedgsgs 之类, 或者几行英文文本.
https://blog.csdn.net/minfanphd/article/details/116975721

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值