//哈夫曼树类
public class HaffmanTree {
//最大权值
static final int MAXVALUE=;
int nodeNum ; //叶子结点个数 public HaffmanTree(int n)
{
this.nodeNum = n;
} //构造哈夫曼树算法
public void haffman(int[] weight,HaffNode[] nodes)//权值数组,所有节点数组
{
int n = this.nodeNum;
//m1,m2,表示最小的两个权值,x1,x2,表示最小两个权值对应的编号,m1表示最小,m2表示次小
int m1,m2,x1,x2; //初始化所有的结点,对应有n个叶子结点的哈夫曼树,有2n-1个结点。
for(int i=;i < *n-;i++)
{
HaffNode temp = new HaffNode();
//初始化n个叶子结点,就是输入的节点。0、1、2、3是叶子节点也是输入的节点
if(i < n)
{
temp.weight = weight[i];
}
else
{
temp.weight = ;
}
temp.parent = ;
temp.flag = ;
temp.leftChild = -;
temp.rightChild = -;
nodes[i] = temp;
} for(int i=;i<n-;i++){//初始化n-1个非叶子结点,n-1表示要循环n-1次求的n-1个数。
m1 = m2 = MAXVALUE;
x1 = x2 =;
for(int j=;j< n+i;j++)//求得这n-1个数时,每次都是从0到n+i-1,并且flag=0的,flag=1表示已经加入到二叉树。
{ //以下2步是找出权值最小的2个
if(nodes[j].weight<m1 && nodes[j].flag==)//if成立了else、else if就不进去了。
{
//m1,x1初始值为第一个元素,后面如果比m1要小,则m1指向更小的,原来m1指向的现在由m2指向,
//如果后面比m1大比m2小,则m2指向这个比m1大比m2小的,
//也就是说m1指向最小的,m2指向第2小的。
m2 = m1;
x2 = x1;
m1 = nodes[j].weight;
x1 = j;
}
else if(nodes[j].weight<m2 && nodes[j].flag ==)
{
m2 = nodes[j].weight;
x2 = j;
}
}
//将权值最小的2个组合成一个2插树
nodes[x1].parent = n+i;
nodes[x2].parent = n+i;
nodes[x1].flag = ;
nodes[x2].flag = ;
nodes[n+i].weight = nodes[x1].weight + nodes[x2].weight;
nodes[n+i].leftChild = x1;
nodes[n+i].rightChild = x2;
}
/*
初始化数组之后:[1,3,5,7,4,9,16]
编码:100、101、11、0
*/
} //哈弗曼编码算法
public void haffmanCode(HaffNode[] nodes,Code[] haffCode)
{
int n = this.nodeNum;
Code code = new Code(n);//
int child,parent; for(int i=;i<n; i++)//给前面n个输入的节点进行编码
{
code.start = n-;//
code.weight = nodes[i].weight;//
child = i;//
parent = nodes[child].parent;
//从叶子节点向上走来生成编码,画图即可。
while(parent!=)
{
if(nodes[parent].leftChild == child)
{
code.bit[code.start] = ;
}
else
{
code.bit[code.start] = ;
} code.start--;
child = parent;
parent = nodes[child].parent;
} Code temp = new Code(n);
for(int j=code.start+;j < n;j++)
{
temp.bit[j] = code.bit[j];
}
temp.weight = code.weight;
temp.start = code.start;
haffCode[i] = temp;
}
}
} //哈夫曼树的结点类
public class HaffNode { int weight; //权值
int parent ;//他的双亲
int flag ;//标志,是否为叶子节点
int leftChild; //他的左孩子
int rightChild;//他的右孩子 HaffNode()
{ } } //哈夫曼编码类
public class Code { int[] bit; //编码的数组
int start; //编码的开始下标
int weight; //权值
Code(int n){
bit = new int[n];
start = n-;
}
} public class Test { public static void main(String[] args) { int n = ;
int[] weight = {,,,};
HaffmanTree haffTree = new HaffmanTree(n);
HaffNode[] nodes = new HaffNode[*n-];
Code[] codes = new Code[n];
//构造哈夫曼树
haffTree.haffman(weight, nodes);
//生成哈夫曼编码
haffTree.haffmanCode(nodes, codes); //打印哈夫曼编码
for(int i=;i<n;i++)
{
System.out.print("Weight="+codes[i].weight+" Code=");
for(int j=codes[i].start+;j<n;j++)
{
System.out.print(codes[i].bit[j]);
}
System.out.println();
}
} }

哈夫曼树:

带权路径长度是做小的,要使一棵二叉树的带权路径长度WPL值最小,必须使权值越大的叶结点越靠近根结点。哈夫曼提出的构造哈夫曼树构造算法为:
(1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根 结点的二叉树,从而得到一个二叉树森林F={T1,T2,…,Tn}。
(2)在二叉树森林F中选取根结点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,新的二叉树的根结点权值为左右子树根结点权值之和。
(3)在二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树加入到二叉树森林F中。
(4)重复步骤(2)和(3),当二叉树森林F中只剩下一棵二叉树时,这棵二叉树就是所构造的哈夫曼树。

哈夫曼编码问题:

哈夫曼树可用于构造代码总长度最短的编码方案。具体构造方法如下:
设需要编码的字符集合为{d1,d2,…,dn},各个字符在电文中出现的次数集合为{w1,w2,…,wn},以d1,d2,…,dn作为叶结点,以w1,w2,…,wn作为各叶结点的权值构造一棵二叉树,规定哈夫曼树中的左分支为0,右分支为1,则从根结点到每个叶结点所经过的分支对应的0和1组成的序列便为该结点对应字符的编码。这样的代码总长度最短的不等长编码称之为哈夫曼编码。

java 哈夫曼编码的更多相关文章

  1. 20172332 2017-2018-2 《程序设计与数据结构》Java哈夫曼编码实验--哈夫曼树的建立,编码与解码

    20172332 2017-2018-2 <程序设计与数据结构>Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 哈夫曼树 1.路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子 ...

  2. java实现哈夫曼编码

    java实现哈夫曼编码 哈夫曼树   既然是学习哈夫曼编码,我们首先需要知道什么是哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫 ...

  3. Java实现哈夫曼编码和解码

    最近无意中想到关于api返回值加密的问题,譬如我们的api需要返回一些比较敏感或者重要不想让截获者得到的信息,像如果是做原创图文的,文章明文返回的话则有可能被抓包者窃取. 关于请求时加密的方式比较多, ...

  4. java使用优先级队列实现哈夫曼编码

    思路: 构建小根堆 根据小根堆实现哈夫曼树 根据哈夫曼树对数据进行编码 代码实现如下: /** * @Author: DaleyZou * @Description: 使用java实现一个哈夫曼编码的 ...

  5. Java数据结构(十二)—— 霍夫曼树及霍夫曼编码

    霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...

  6. Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)

     赫夫曼树 1 基本介绍 1) 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 最优二叉树,也称为哈夫曼树(Huffman Tree), ...

  7. 2018.2.14 Java中的哈夫曼编码

    概念 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造 ...

  8. 10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压

    最终结果哈夫曼树,如图所示: 直接上代码: public class HuffmanCode { public static void main(String[] args) { //获取哈夫曼树并显 ...

  9. HDU2527 哈夫曼编码

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

随机推荐

  1. Yii 1.1 URL两个笔记 同时支持PATH于GET路由和隐藏index.php

    同时支持PATH于GET格式路由(修改框架文件 简直坑) framework/web/CUrlManager.php parseUrl方法 第一行判断修改成 if($this->getUrlFo ...

  2. vmware下ubuntu14.04调整分辨率

    很多人在vmware中安装ubuntu时,为了调整屏幕分辨率,都去下载并安装vmware-tools.其实,这是没有必要的.如果你需要vmware和宿主机实现共享,或者为了使文件能拖进拖出,再或者是需 ...

  3. Codeforces 597C. Subsequences (树状数组+dp)

    题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长 ...

  4. ODBC 是什么

    In computing, ODBC (Open Database Connectivity) is a standard programming language middleware API fo ...

  5. C#中的DllImport

    大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如 Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功 ...

  6. JS、jqueryie6浏览器下使用js无法提交表单的解决办法

    -----------------------JS.jqueryie6浏览器下使用js无法提交表单的解决办法---------------------------------------------- ...

  7. OC: NSString、NSArray、NSNumber

    数组参考: 参考1  参考2  参考3 //字符串 //1.获取字符串的长度: //表情符号最少占两个字节 NSString * s = @"中文字符串

  8. 读写锁:ReadWriteLock

    http://my.oschina.net/20076678/blog/173165   一.在JDK文档中关于读写锁的相关说明 ReadWriteLock 维护了一对相关的 锁 ,一个用于只读操作, ...

  9. 关于mysql函数GROUP_CONCAT

    GROUP_CONCAT()是MySQL数据库提供的一个函数,通常跟GROUP BY一起用,具体可参考MySQL官方文挡:http://dev.mysql.com/doc/refman/5.0/en/ ...

  10. 连接SQLServer时提示“但是在登录前的握手期间发生错误。 (provider: SSL Provider, error: 0 - 等待的操作过时”解决办法

    解决:"已成功与服务器建立连接,但是在登录前的握手期间发生错误. (provider: SSL Provider, error: 0 - 等待的操作过时" 官方问题介绍:http: ...