....差点忘记写博客了...
哈夫曼树 .. 其实就是只利用叶子结点来存储要用信息的树,只不过它在构造的时候就拥有了一个迷人的特性... 就是WPL(带权路径长度)是最小的.. 而且还能用这个树的来为叶子结点中的信息进行编码, 得出来的各个编码一定不会相同,并且不会产生混淆的情况..
通过哈夫曼树的特点.实现了根据一个队列来创建一棵哈夫曼树的方法.
/** * 得到随机产生的队列 */ public void setQueue() { Random rd = new Random(); System.out.println("随机产生的队列为:"); for (int i = 0; i < 10; i++) { int k = rd.nextInt(20); TreeNode tn = new TreeNode(k); queue.add(tn); System.out.print(k + " "); } System.out.println(); } // 得到队列 public PriorityQueue<TreeNode> getQueue() { return queue; } // 建树,while (queue.size()>=2) public TreeNode CreatTree(PriorityQueue<TreeNode> queue) { TreeNode lc = queue.poll(); TreeNode rc = queue.poll(); // 两个最小的结点通过这个结点连接起来 TreeNode tr = new TreeNode((Integer) lc.getData() + (Integer) rc.getData()); tr.setLchild(lc); tr.setRchild(rc); lc.setParent(tr); rc.setParent(tr); // 将其父结点放入队列. queue.add(tr); return tr;// 将根结点返回.当返回到最后一个根结点时就构成了一棵树 }
到此.. 哈夫曼树就建成了. 接下来就是哈夫曼编码了.这个的实现我用到了递归,并且是每个叶结点往回找
/** * 为每个叶结点编码,返回字符串 * * @param leaf每次传入一个叶结点 * @return以字符串形式返回每个叶结点的哈夫曼编码 */ public String ToCode(TreeNode leaf) { String s = ""; // 叶结点存在双亲结点. if (leaf.getParent() != null) { if (leaf.getParent().getLchild() == leaf) { // 向父结点递归 s = ToCode(leaf.getParent()) + 0; return s;// 叶结点为左孩子时,在递归得到的编码后面加个0; } else if (leaf.getParent().getRchild() == leaf) { // 向父结点递归 s = ToCode(leaf.getParent()) + 1; return s;// 叶结点为右孩子时,在递归得到的编码后面加个1; } } return s; }
补充个.. 今天读取文件中的字节时..发现0出现的次数是最多的 ... 读了个162M的文件.. 0的个数比其他的数出现的次数多了10万次 ....