`
wuzexin530
  • 浏览: 18566 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论
阅读更多

       还记得第一次接触哈夫曼树是在大二的数据结构课上,大家也都知道哈树的生成规则,很简单也很容易理解。给你N个带权的节点,让你生成一颗哈树,相信大部分人都没有问题。而正是这种表面看似很简单的东西,我们就容易无视。我坦白,那年数据结构的学习,对于哈树这一块,我没有敲过一行代码,更没有去想过他存在的意义以及利用哈树能解决什么样的问题。

       大三进入蓝杰,重新接触到了哈夫曼树。这个沉寂在我脑海已久且濒临消亡的知识点,仿佛又渐渐地回来了。也让我开始思考哈夫曼树存在的意义。在IT这么一个日新月异的领域,一个技术之所以能够存在,一定是有其价值的,他一定是能给我们决绝问题带来利益的。通过查找给方面的资料,发现哈弗曼的用处确实很广,尤其是在数据通信、图像处理、数据压缩等方面有着很大的用处。

       下面,我想通过手动建造一棵哈夫曼树,再次走进哈夫曼的世界。 ------

一、哈弗曼的基础知识

      大家要了解一下哈夫曼树的基础知识。网上有很多解释,度娘说的比我清楚,这里就不占用篇幅多做解释。

     下图是建造一颗哈树的过程....

二、 进入主题--------代码的实现

     

    (1)首先,定义一个树的节点类

/**
 * 哈夫曼树节点的定义
 * 
 * @author Administrator
 * 
 */
public class HuffmanNode {
	// 成员属性
	private HuffmanNode left_child = null;
	private HuffmanNode right_child = null;
	private HuffmanNode parend = null;
	// 权值
	private int obj;

	public HuffmanNode getLeft_child() {
		return left_child;
	}

	public void setLeft_child(HuffmanNode left_child) {
		this.left_child = left_child;
	}

	public HuffmanNode getRight_child() {
		return right_child;
	}

	public void setRight_child(HuffmanNode right_child) {
		this.right_child = right_child;
	}

	public HuffmanNode getParend() {
		return parend;
	}

	public void setParend(HuffmanNode parend) {
		this.parend = parend;
	}

	public int getObj() {
		return obj;
	}

	public void setObj(int obj) {
		this.obj = obj;
	}

	// 构造函数
	public HuffmanNode(int obj) {
		this.obj = obj;
	}

}

 

(2)生成一颗哈树

         这里用到了一个新的知识点---优先队列。因为哈夫曼树的构造规则是每次要取根节点权值最小的两棵树出来。所以我们必须根据这些根节点权值大小,将这些树进行排序。 优先队列恰好为我们提供了这项功能,我们通过重新定义Comparator比较器,可以设定自己想要的排序规则,十分方便。

Comparator<HuffmanNode> comparator = new Comparator<HuffmanNode>() {

			@Override
			public int compare(HuffmanNode o1, HuffmanNode o2) {
				int numbera = o1.getObj();
				int numberb = o2.getObj();
				if (numberb < numbera) {
					return 1;
				} else if (numberb > numbera) {
					return -1;
				} else {
					return 0;
				}

			}
		};

 

核心语句----哈树的生成

              从森林中每次取根节点权值最小的两棵树出来,形成一棵新树,其权值为两树根绝点权值之和。并将这两棵树分别作为新树的左右子树。循环往复,知道深林中只剩下1棵树。那么,这棵树就是我们要找的哈夫曼树。

/**
	 *  生成哈夫曼树的方法
	 * @param queue 优先队列
	 */
	private void creathuffman(PriorityQueue<HuffmanNode> queue) {
		while (queue.size() != 1) {
			// 取得两个最小的节点
			HuffmanNode node1 = queue.poll();
			HuffmanNode node2 = queue.poll();
			// 生成一个新的节点
			HuffmanNode node3 = new HuffmanNode(node1.getObj() + node2.getObj());
			node3.setLeft_child(node1);
			node3.setRight_child(node2);
			queue.add(node3);
		}
	}

 

(3)打印所生成的哈树(通过先序遍历)

        

// 打印哈夫曼树的方法
	private void printhuffman(HuffmanNode rootnode) {
		// 指定根节点,从根节点开始找
		HuffmanNode temp = rootnode;
		// 打印根节点的值
		System.out.print("【"+temp.getObj()+"】" + "  ");
		if (rootnode.getLeft_child() != null) {
			temp = rootnode.getLeft_child();
			// 递归调用自己,表示只要左节点不为空,就把左节点作为新的根节点继续上边步奏
			printhuffman(temp);
		}
		if (rootnode.getRight_child() != null) {
			temp = rootnode.getRight_child();
			printhuffman(temp);// 同上
		}
	}

 

         至此,我们的哈夫曼树的生成过程已经演示完毕。刚才也说了,哈夫曼树的用处还有很多,我们能够创建他,也只是完成其中最基础的要求,我们不能止步于此。当然,我们不能认为这些东西很简单,就去轻视他,自己没有动手做过,你是不会知道什么叫做说着简单做着难的。

          好啦, 之后我们会通过一个文件压缩程序的演示,其中包括了哈弗曼编码的生成,对象的序列化,文件的读出与写入等问题,跟大家进一步分享哈弗曼在数据编码上的用途。 

  • 大小: 28.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics