Java数据结构之哈夫曼树

背景

由于目前常用的图像、音频等多媒体的信息量巨大,因此必须采用数据压缩技术来存储和传输。数据压缩技术通过对数据进行重新编码来压缩存储,以便减少数据占用的存储空间,在使用时再进行解压缩,恢复数据的原有特性。
压缩方法主要由有损压缩和无损压缩。有损压缩是指压缩过程中可能会丢失数据信息;无损压缩是指压缩存储数据的全部信息,保证解压后的数据不丢失。哈夫曼编码是一种无损压缩技术。

基本概念

  1. 结点间路径:从一个结点到另一个结点所经过的结点序列
  2. 结点路径长度:从根结点到结点的路径上的边数
  3. 结点的权值:人为赋予结点的一个具有某种实际意义的值(例:可以为某个数出现的频数等)
  4. 结点的带权路径长度:结点的权值和结点的路径长度的乘积
  5. 树的带权路径长度:树的叶节点的带权路径长度之和(WPL)
  6. 最优二叉树:指n个带有权值的叶子结点作为二叉树, 构造出的具有最小带权路径长度的二叉树,即哈弗曼树

特点

  1. 权值大的,路径短,权值小的,路径大;
  2. 只有度为0(叶子结点)和度为2(分支结点)的结点,不存在度为1的结点

核心思想

由给定的n个结点作为根结点构成森林,依次选取其中权值最小的两个根结点作为左右子结点,并向上合并构成其父节点。将该父节点加入森林,并同时删除已选中的两个子结点。重复抽取,直到森林中只有一颗树为止。

  1. 初始化:由给定n个具有确定权值的树构成森林,森林中的每个树只有根结点,即{w1,w2,w3,…,wn},其中wi为权值
  2. 选取与合并:从森林中选取权值最小的两个树,分别作为左右子树从而构成一个新的树,新树的根结点权值为这两个左右子树的权值之和
  3. 添加与删除:从森林中删除选出的两个树,同时加入新生成的树
  4. 重复:继续循环(2)(3)步骤,知道只剩一个树为止,即为哈弗曼树

存储结构

  1. 设置长度为2n-1的数组(n为森林中根结点个数,最多具有2n-1个结点)
  2. 以链表结构构造哈夫曼结点

实现代码

public class HuffmanTree {
	private class HuffmanNode{
		public int weight;//哈夫曼结点的权重
		public boolean flag;//标记是否已经进入哈弗曼树
		public HuffmanNode lchild,rchild,parent;//保存当前节点的左右孩子结点及双亲结点
		
		HuffmanNode(){
			this(0);
		}
		
		HuffmanNode(int weight){
			this.weight = weight;
			flag = false;
			lchild = rchild = parent = null;
		}
		
	}
	
	/**
	 * 根据根结点权值数组构建哈夫曼树
	 * @param w	所有结点的权值构成的数组
	 */
	public HuffmanTree(int[] w) {
		int l = w.length;
		int n = 2 * l - 1;// 哈夫曼结点数
		HuffmanNode[] node = new HuffmanNode[n];
		for(int i=0;i

你可能感兴趣的:(Java数据结构)