哈夫曼编码实验
时间:2019-11-22
本文章向大家介绍哈夫曼编码实验,主要包括哈夫曼编码实验使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
哈夫曼的编码实验
一、哈夫曼编码介绍:
- 1、哈夫曼树:
(1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树。
(2)特点:哈夫曼树中没有度为1的结点,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n个叶子节点的哈夫曼树共有2n-1个节点。 - 2、哈夫曼编码步骤:
- (1)计算字符出现的次数:
- 假设我们现在有一段文档需要进行编码,我们现在需要对于每一个字符出现的次数进行统计,然后分别计算出其在这篇文档的权重,也就是频率,我们用下面的一段文字进行举例;
- 在如下的文档中包括的字符有8个字母和2个空格,所以我们现在需要去统计这10个字符的个数,统计后的数据如下:
- (2)对字符出现的次数作为一个权重,从小到大进行排序;
- (3)依照排序结果从小到大根据以下规则进行造树:
- a、最小的前两个数进行权重的相加,形成他们两个作为左子树和右子树的父结点,如果是左结点就标记为0,如果是右结点就标记为1
- b、然后将父结点作为一个新的结点进入排序结果,之后进行重新排序(ps:假如出现添加后的父结点的权重和之前排序中的结点的权重相等的情况,两者的位置具体是对于建树没有影响的,但是在编程实现的过程中,程序需要将两者的位置进行确定)
- c、重复上述过程,直到得到的父结点的权重为1。
- (1)计算字符出现的次数:
代码构建过程:
字符出现的次数统计:
String source="We go the hustler you've got to hustle There ain't no time for sleep Just keep on movin' do what you're doing ";
String[] b = source.split("");
int an=0;
int bn=0;
int cn=0;
int dn=0;
int en=0;
int fn=0;
int gn=0;
int hn=0;
int in=0;
int jn=0;
int kn=0;
int ln=0;
int mn=0;
int nn=0;
int on=0;
int pn=0;
int qn=0;
int rn=0;
int sn=0;
int tn=0;
int un=0;
int vn=0;
int wn=0;
int xn=0;
int yn=0;
int zn=0;
int zkongge=0;
for (int i =0;i<b.length;i++){
if (b[i].equals("a")){
an++;
}
if (b[i].equals("b")){
bn++;
}
if (b[i].equals("c")){
cn++;
}
if (b[i].equals("d")){
dn++;
}
if (b[i].equals("e")){
en++;
}
if (b[i].equals("f") ){
fn++;
}
if (b[i].equals("g")){
gn++;
}
if (b[i].equals("h")){
hn++;
}
if (b[i].equals("i")){
in++;
}
if (b[i].equals("j")){
jn++;
}
if (b[i].equals("k")){
kn++;
}
if (b[i].equals("l")){
ln++;
}
if (b[i].equals("m")){
mn++;
}
if (b[i].equals("n")){
nn++;
}
if (b[i].equals("o")){
on++;
}
if (b[i].equals("p")){
pn++;
}
if (b[i].equals("q")){
qn++;
}
if (b[i].equals("r")){
rn++;
}
if (b[i].equals("s")){
sn++;
}
if (b[i].equals("t")){
tn++;
}
if (b[i].equals("u")){
un++;
}
if (b[i].equals("v")){
vn++;
}
if (b[i].equals("w")){
wn++;
}
if (b[i].equals("x")){
xn++;
}
if (b[i].equals("y")){
yn++;
}
if (b[i].equals("z")){
zn++;
}
}
Objects Za= new Objects("a",an);
Objects Zb = new Objects("b",bn);
Objects Zc = new Objects("c",cn);
Objects Zd = new Objects("d",dn);
Objects Ze = new Objects("e",en);
Objects Zf = new Objects("f",fn);
Objects Zg = new Objects("g",gn);
Objects Zh = new Objects("h",hn);
Objects Zi = new Objects("i",in);
Objects Zj = new Objects("j",jn);
Objects Zk = new Objects("k",kn);
Objects Zl = new Objects("l",ln);
Objects Zm = new Objects("m",mn);
Objects Zn = new Objects("n",nn);
Objects Zo = new Objects("o",on);
Objects Zp = new Objects("p",pn);
Objects Zq = new Objects("q",qn);
Objects Zr = new Objects("r",rn);
Objects Zs = new Objects("s",sn);
Objects Zt = new Objects("t",tn);
Objects Zu = new Objects("u",un);
Objects Zv = new Objects("v",vn);
Objects Zw = new Objects("w",wn);
Objects Zx = new Objects("x",xn);
Objects Zy = new Objects("y",yn);
Objects Zz = new Objects("z",zn);
System.out.println("各个字符的概率统计为:");
Objects[] temp = new Objects[]{Za,Zb,Zc,Zd,Ze,Zf,Zg,Zh,Zi,Zj,Zk,Zl,Zm,Zn,Zo,Zp,Zq,Zr,Zs,Zt,Zu,Zv,Zw,Zx,Zy,Zz};
2、哈夫曼编码&解码:
private Map<Character,Integer> map=new HashMap<>();
private Map<Character,String> ce=new HashMap<>();
private PriorityQueue<Tree> trees=new PriorityQueue<>();
private String source;
private String result;
public void init(String source){
this.source=source;
char[] chars= source.toCharArray();
for (char c :chars){
if (!map.containsKey(c)){
map.put(c,1);
}else {
map.put(c,map.get(c)+1);
}
}
afterInit();
}
private void afterInit() {
map.forEach((c,count)->{
Node<Character> node=new Node<>();
node.key=count;
node.charData=c;
Tree tree=new Tree();
tree.setRoot(node);
trees.add(tree);
});
}
public void build(){
while (this.trees.size()>1){
Tree left=this.trees.poll();
Tree right=this.trees.poll();
Node node=new Node();
node.key=left.getRoot().key+right.getRoot().key;
node.leftChild=left.getRoot();
node.rightChild=right.getRoot();
left.setRoot(node);
this.trees.add(left);
}
}
public void encoding(){
Tree tree=this.trees.peek();
this.encoding(tree.getRoot(),"");
}
public String encodingResult(){
StringBuilder sb=new StringBuilder();
char[] chars= source.toCharArray();
for (char c :chars){
sb.append(ce.get(c)+' ');
}
return sb.toString();
}
private void encoding(Node<Character> node,String encoding){
if (node!=null){
if (node.leftChild==null && node.rightChild==null){
ce.put(node.charData,encoding);
}
encoding(node.leftChild,encoding+"0");
encoding(node.rightChild,encoding+"1");
}
}
public void displayTree(){
Tree tree=this.trees.peek();
tree.inDisplay(tree.getRoot());
}
public void displayEncodeing(){
ce.forEach((k,v)->{
System.out.println(k+":"+v);
});
}
3、中序遍历建立哈夫曼树:
package Exp9.Hufman;
public class Tree implements Comparable<Tree>{
private Node root;
public Node getRoot() {
return root;
}
public void setRoot(Node root) {
this.root = root;
}
/**
*中序遍历法
*/
public void inDisplay(Node node){
if (node!=null){
inDisplay(node.leftChild);
System.out.println(node.key+":"+node.charData);
inDisplay(node.rightChild);
}
}
public void postDisplay(Node node){
if (node!=null){
postDisplay(node.leftChild);
postDisplay(node.rightChild);
System.out.print(node.key+":"+node.charData);
}
}
@Override
public int compareTo(Tree o) {
if (this.root.key>o.root.key){
return 1;
}else if (this.root.key==o.root.key){
return 0;
}else {
return -1;
}
}
}
完整代码
实验结果:
参考资料:
原文地址:https://www.cnblogs.com/Stark-GR/p/11911987.html
- ORM查询语言(OQL)简介--实例篇
- 漏洞预警 | 海洋CMS(SEACMS)0day漏洞预警
- 【机器学习】分类算法评价
- Java中图片处理工具类——能满足各种需求
- onclicklistener到底怎么用?
- 如何入侵联网智能灯泡——LIFX智能灯泡
- Java实现的一个编号生成器工具类——5种方法
- 【机器学习】有趣的机器学习:最简明入门指南
- 不使用反射,“一行代码”实现Web、WinForm窗体表单数据的填充、收集、清除,和到数据库的CRUD
- 海量数据处理利器之布隆过滤器
- ORM查询语言(OQL)简介--概念篇
- Discuz! 任意文件删除漏洞重现及分析
- .NET DLR 上的IronScheme 语言互操作&&IronScheme控制台输入中文的问题
- Java中Map相关的6大问题——每个开发人员都要注意
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 打卡群刷题总结0810——从前序与中序遍历序列构造二叉树
- JavaScript性能优化
- Python+Excel+Word一秒制作百份合同
- SQL 订单揽收统计
- LeetCode11|搜索二维矩阵
- LeetCode14|合并排序的数组
- LeetCode12|两个数组的交集
- LeetCode10|只出现一次的数字II
- LeetCode15|有序数组中出现次数超过25%的元素
- 小米5(gemini:双子座)刷机
- Cygwin本地安装版
- arm-gcc各版本区别
- LeetCode13|最小k个数
- 通过USB连接方式共享安卓的网络连接
- Spring事务专题(四)Spring中事务的使用、抽象机制及模拟Spring事务实现