最终结果哈夫曼树,如图所示:

直接上代码:

public class HuffmanCode {
public static void main(String[] args) {
//获取哈夫曼树并显示
Hnode root = createHuffmanTree(createNodes());
root.beforePrint();
System.out.println("====================");
//从哈夫曼树中读取 哈夫曼编码
getHuffmanCode(root);
//从huffmanCodes 中读取哈夫曼编码:A:10, B:01, C:0011,D:11,E:000,F:00100,G:00101
System.out.println("哈夫曼编码为:"+huffmanCodes);
} //创建一个 Hnode节点的集合
public static List<Hnode> createNodes(){
List<Hnode> nodes = new ArrayList<Hnode>();
nodes.add(new Hnode(new Person(12,"A"),60));
nodes.add(new Hnode(new Person(13,"B"),45));
nodes.add(new Hnode(new Person(14,"C"),13));
nodes.add(new Hnode(new Person(15,"D"),69));
nodes.add(new Hnode(new Person(16,"E"),14));
nodes.add(new Hnode(new Person(17,"F"),5));
nodes.add(new Hnode(new Person(18,"G"),3));
return nodes;
}
//根据list 创建哈夫曼树
public static Hnode createHuffmanTree(List<Hnode> nodes){
while(nodes.size() > 1){
//先对 nodes进行从小到大排序, 根据权重值进行从小到大排序
Collections.sort(nodes, new Comparator<Hnode>() {
public int compare(Hnode o1, Hnode o2) {
return o1.weight - o2.weight;
}
});
//取出前二个最小的元素,构建一个父节点只有权重 没有数据的二叉树
Hnode leftNode = nodes.get(0);
Hnode rightNode = nodes.get(1);
Hnode parent = new Hnode(null, leftNode.weight + rightNode.weight);
parent.leftNode = leftNode;
parent.rightNode = rightNode; //将原来nodes中已经处理的前二个最小元素删除调,并将parent节点存入nodes中
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
//循环结束时候,nodes中只有一个节点了,且该节点就是哈夫曼树的根节点
return nodes.get(0);
} static StringBuilder stringBuilder = new StringBuilder();
static Map<String,String> huffmanCodes = new HashMap<String, String>();
//从哈夫曼树中读取 哈夫曼编码: A:10, B:01, C:0011,D:11,E:000,F:00100,G:00101
public static void getHuffmanCode(Hnode root){
if (root == null) {
return ;
}
getCode(root.leftNode,"0",stringBuilder);
getCode(root.rightNode,"1",stringBuilder);
} private static void getCode(Hnode node, String code, StringBuilder builder) {
StringBuilder builder1 = new StringBuilder(builder);
builder1.append(code);
if (node != null) {
if (node.person == null) {
//如果数据为不null,说明是子节点
//左递归处理
getCode(node.leftNode,"0",builder1);
//右递归处理
getCode(node.rightNode,"1",builder1);
}else{
//如果数据为null,说明是叶子节点
huffmanCodes.put(node.person.name,builder1.toString());
}
}
}
} //先建节点
class Hnode{
Person person;//数据
int weight;//权重
Hnode leftNode;
Hnode rightNode; public Hnode(Person person, int weight) {
this.person = person;
this.weight = weight;
} @Override
public String toString() {
return "Hnode{" +
"data='" + person + '\'' +
", weight=" + weight +
'}';
}
//前序遍历
public void beforePrint(){
System.out.println(this);
if (this.leftNode != null) {
this.leftNode.beforePrint();
}
if (this.rightNode != null) {
this.rightNode.beforePrint();
}
}
} class Person {
int age;
String name; public Person(int age, String name) {
this.age = age;
this.name = name;
} @Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}

结果如下:

压缩原理:

1: 被压缩文件通过输入流,转化为原始字节数组, 遍历统计每个字节出现的次数,并转化为map, key:字节,value:该字节的次数

2: map 转化为list,根据list创建 哈夫曼树,并获取到对应的哈夫曼编码

3: 将哈夫曼编码转化字节数组,通过输出流,写入到目标文件中,同时将哈夫曼编码也写入到目标文件中(目的:是为了解码使用)

解压缩原理:

1: 通过输入流从被解压缩文件中,读取到哈夫曼编码,和 哈夫曼编码转化字节数组,

2: 解码 得到原始字节数组, 并将数组写出到目标文件中

10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压的更多相关文章

  1. Java数据结构和算法(七)B+ 树

    Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...

  2. java 文件压缩和解压(ZipInputStream, ZipOutputStream)

    最近在看java se 的IO 部分 , 看到 java 的文件的压缩和解压比较有意思,主要用到了两个IO流-ZipInputStream, ZipOutputStream,不仅可以对文件进行压缩,还 ...

  3. java文件压缩和解压

    功能实现. package com.test; import java.io.File; import java.io.BufferedOutputStream; import java.io.Buf ...

  4. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

  5. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

  6. 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现

      本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型   栈是 ...

  7. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

  8. java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...

  9. Java数据结构和算法 - 高级排序

    希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...

随机推荐

  1. LNMP环境搭建Wordpress博客

    目录 LNMP架构工作原理 yum源安装 网站源包安装 LNMP是Linux Nginx MySQL/MariaDB  Php/perl/python 的简称,是近些年才逐渐发展起来的构架,发展非常迅 ...

  2. Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)

    7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...

  3. 12.PHP_PDO数据库抽象层

    PDO数据库抽象层 其实也就是说,为了方便PHP项目各种数据库切换的方便以及代码兼容性,再各种数据库上又封装了一层,做成了统一的接口,方便数据库使用和切换. PDO链接mysql数据库: <?p ...

  4. Intel汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-下

    4.3  和数据相关的操作符和伪指令 操作符和伪指令并非机器可执行的指令,相反,它们是由汇编器进行解释的.开发者可以使用一系列的MASM操作符或伪指令获取数据的地址以及大小等特征信息: OFFSET操 ...

  5. Spring Cloud Alibaba(7)---docker-compose搭建nacos1.4.0集群

    docker-compose搭建nacos1.4.0集群 有关Nacos之前写过四篇文章. Spring Cloud Alibaba(3)---Nacos概述 Spring Cloud Alibaba ...

  6. 支付宝手机端网页支付 PHP(基于官方提供的demo)

    1.支付宝开放平台添加应用并且签约快捷手机wap支付(应用添加不做详细说明) 2.下载demo,文档中心SDK&Demo, 3.个人中心秘钥管理,查看商户appID,商户私钥,支付宝公钥,商户 ...

  7. NumPy之:理解广播

    目录 简介 基础广播 广播规则 简介 广播描述的是NumPy如何计算不同形状的数组之间的运算.如果是较大的矩阵和较小的矩阵进行运算的话,较小的矩阵就会被广播,从而保证运算的正确进行. 本文将会以具体的 ...

  8. SparkSQL电商用户画像(五)之用户画像开发(客户基本属性表)

    7.电商用户画像开发 7.1用户画像--数据开发的步骤 u 数据开发前置依赖 -需求确定 pv uv topn -建模确定表结构 create table t1(pv int,uv int,topn ...

  9. QFNU 10-02 19 training

    B - Yet Another Crosses Problem 题意:找如果使图中某一行某一列全部变成黑色,至少需要把多少个白方格变成黑方格 思路:直接找就可以,注意存储的时候要记得进行分开存储,存储 ...

  10. Pytorch_Part7_模型使用

    VisualPytorch beta发布了! 功能概述:通过可视化拖拽网络层方式搭建模型,可选择不同数据集.损失函数.优化器生成可运行pytorch代码 扩展功能:1. 模型搭建支持模块的嵌套:2. ...