简单哈弗曼树(Java)

哈夫曼树的实现


  1.编码思想

    哈夫曼编码是一种变长的编码方案,字符的编码根据使用频率的的不同而长短不一, 使用频率高的字符其编码较短,使用频率低的字符编码较长,从而使所有的编码总长度为最短.

  1. 统计原始数据中个新号符号的频率,安频率高低的次序排列
  2. 将两个频率最小的相加,作为原本两个节点的父节点,次父节点的频率为子节点之和
  3. 重复上述两部,直到和为只剩下一个元素,那么这个元素就是根

2.解码思想

利用Haffman树进行解码,已知一个二进制位串S,从串S的第一位出发,逐位的去匹配二叉树边上标记的0和1,从haffman树的根节点出发,遇到0时,向左,遇到1时向右,若干连续的0和1确定一条从根节点到某个叶子节点的路径.一旦到达一个叶子节点,便译出一个字符,接着从S的下一个位开始继续寻找.



解码如上.

编码实现如下:

 1 package com.practice;
 2
 3 /**
 4  * 二叉树的静态三叉链表表示法
 5  */
 6 public class TriElement {
 7     int data ;
 8     int parent, left, right ;
 9     public TriElement(int data, int parent, int left, int right) {
10         this.data = data ;
11         this.parent = parent ;
12         this.left = left ;
13         this.right = right ;
14     }
15     public TriElement(int data) {
16         this(data, -1, -1, -1) ;
17     }
18     public TriElement() {
19         this(0) ;
20     }
21
22     @Override
23     public String toString() {
24         return "(" + this.data + "," + this.parent + "," + this.left + "," + this.right + ")" ;
25     }
26 }
 1 package com.practice;
 2
 3 /**
 4  * 依靠静态链表实现的哈弗曼树
 5  */
 6 public class BuffmanTree {
 7     private int leafNum ;
 8     private TriElement[] hufftree ;
 9     public BuffmanTree(int[] weights) {
10         int n = weights.length ;
11         this.leafNum = n ;
12         //用完全二叉树存储,所以需要
13         //申请2 * n - 1个空间
14         this.hufftree = new TriElement[2 * n - 1] ;
15         for(int i = 0 ; i < n; ++i) {
16             this.hufftree[i] = new TriElement(weights[i]) ;
17         }
18
19         //需要新创建n-1个(2度节点)
20         //(2 * n - 1) - n
21         for(int i = 0 ; i < n - 1; ++i) {
22             int min1 = Integer.MAX_VALUE ;
23             int min2 = min1 ;
24             int p1 = -1, p2 = -1 ;
25             for(int j = 0 ; j < n + i ; ++j) {          //在所有的无父母的节点中查找最小的两个节点
26                                                         //当前所有节点只有 n + i 个
27                 if(hufftree[j].data < min1 && hufftree[j].parent == -1) {
28                     min2 = min1 ;
29                     p2 = p1 ;
30                     min1 = hufftree[j].data ;
31                     p1 = j ;
32                 } else if(hufftree[j].data < min2 && hufftree[j].parent == -1) {
33                     min2 = hufftree[j].data ;
34                     p2 = j ;
35                 }
36             }
37             //构造父母节点
38             hufftree[p1].parent = n + i ;
39             hufftree[p2].parent = n + i ;
40             this.hufftree[n + i] = new TriElement(min1 + min2, -1, p1, p2) ;
41         }
42     }
43
44     @Override
45     public String toString() {
46         StringBuilder stringBuilder = new StringBuilder() ;
47         for(int i = 0 ; i < this.hufftree.length && hufftree[i] != null ; ++i) {
48             stringBuilder.append("第" + i + "行" + this.hufftree[i].toString() + "\n") ;
49         }
50         return stringBuilder.toString() ;
51     }
52
53     public String[] toCodes() {
54         String[] huffcodes = new String[this.leafNum] ;
55
56         for(int i = 0 ; i < this.leafNum ; ++i) {
57             huffcodes[i] = "" ;
58             int child = i ;
59             int parent = hufftree[child].parent ;
60             while(parent != -1) {
61                 if(hufftree[parent].left == child) {
62                     huffcodes[i] = "0" + huffcodes[i] ;
63                 } else {
64                     huffcodes[i] = "1" + huffcodes[i] ;
65                 }
66                 child = parent ;
67                 parent = hufftree[child].parent ;
68             }
69         }
70         return huffcodes ;
71     }
72
73     /**
74      * 测试
75      */
76     public static void main(String[] args) {
77         int[] weights = {1,3,5,8,32,12} ;
78         BuffmanTree htree = new BuffmanTree(weights) ;
79         System.out.println("数组细节:");
80         System.out.println(htree.toString()) ;
81
82         String[] codes = htree.toCodes() ;
83         System.out.println("huffman编码: ") ;
84         for(int i = 0 ; i < codes.length ; ++i) {
85             System.out.println((char)(‘A‘ + i) + ": " + codes[i] + "   ");
86         }
87
88     }
89 }

原文地址:https://www.cnblogs.com/jffx/p/9997868.html

时间: 2024-08-10 19:26:20

简单哈弗曼树(Java)的相关文章

java实现哈弗曼树

O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如用于压缩,用于密码学等.今天一起来看看哈弗曼树到底是什么东东. 概念 当然,套路之一,首先我们要了解一些基本概念. 1.              路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,路径上的分支数目称为路径长度. 2.              树的路径长度:从树

(源码,具体的细节请查阅相关资料)哈弗曼树的构造以及非递归遍历树

写了一点haffman树的创建和二叉树的非递归遍历. 如果编写代码的时候出现了,思维断点,可以借鉴一下, 避免浪费一些不必要的时间. 我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占 位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我 是占位符我是占位符我是占位符我是占位符我是占位符我是 占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符我是占位符

【哈弗曼树】HDU 5350 MZL&#39;s munhaff function

通道 题意:根据那个递推式,找找规律即可. 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; typedef long long ll; inline bool rd(int &ret) { char c; int sgn; if(c = getchar(

哈弗曼树的构建,哈夫曼编码、译码

哈夫曼树的基本概念 哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树. (1)路劲(Path):从树中的一个结点到另一个结点之间的分支构成两个结点间的路径. (2)路径长度(Path Length):路径上的分支树. (3)树的路径长度(Path Length of Tree):从树的根结点到每个结点的路径长度之和.在结点数目相同的二叉树中,完全二叉树的路径长度最短. (4)结点的权(Weight of  Node):在一些

哈弗曼树的建立

哈弗曼树也称为最优二叉树,它是带权路径长度最短的树,权值越大的结点就离根节点越近.(一般在哈弗曼编码中,权值表示出现的概率,即出现的概率越大,那么访问时的路径就越短). 构建哈弗曼树: 将n个权值构造出n棵只有根节点的树,构成森林. 在森林中选出两个根结点的权值最小的树分别做左右孩子合并一棵新树,且新树的根结点权值为左右结点之和. 从森林中删除选取的两棵树,并将构成的新想树插入到森林中. 构建哈弗曼树的步骤图解如下. 代码实现: //哈弗曼树 #include <stdio.h> #inclu

哈弗曼树及其操作

1.哈弗曼树的节点声明 1 package com.neusoft.Tree; 2 3 public class HuffmanNode { 4 public int weight; 5 //加入哈夫曼树的标志,flag=0表示该节点没有加入哈夫曼树,=1表示加入 6 public int flag; 7 public HuffmanNode parent,lchild,rchild; 8 public HuffmanNode() { 9 this(0); 10 } 11 public Huff

poj 3253 Fence Repair 【哈弗曼树】+【优先队列】

Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27742   Accepted: 9019 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000)

数据结构&amp;&amp;哈弗曼树和哈弗曼编码

1.什么是哈夫曼树和哈弗曼编码 大家来看这样一道面试题(题目来自于<程序员面试宝典>).用二进制来编码字符串"abcdabaa",需要能够根据编码,解码回原来的字符串,最少需要多长的二进制字符串? A.12 B.14 C.18 D.24 解析:典型的哈弗曼编码问题:字符串"abcdabaa"有4个a.2个b.1个c.1个d.构造哈弗曼树如下图所示(图好丑).a编码0(1位),b编码10(2位),d编码111(3位).二进制字符串的总长度为1*4+2*2+

赫夫曼树JAVA实现及分析

一,介绍 1)构造赫夫曼树的算法是一个贪心算法,贪心的地方在于:总是选取当前频率(权值)最低的两个结点来进行合并,构造新结点. 2)使用最小堆来选取频率最小的节点,有助于提高算法效率,因为要选频率最低的,要么用排序,要么用堆.用堆的话,出堆的复杂度为O(logN),而向堆中插入一个元素的平均时间复杂度为O(1),在构建赫夫曼树的过程中,新生成的结点需要插入到原来的队列中,故用堆来维持这种顺序比排序算法要高效地多. 二,赫夫曼算法分析 ①用到的数据结构分析 首先需要构造一棵赫夫曼树,因此需要二叉链