package com.atguigu.huffmancode;
import java.io.*;
import java.util.*;
/**
* @author Peter
* @date 2022/8/28 11:42
* @description Usage
*/
public class HuffmanCode {
static Map<Byte, String> huffmanCodes = new HashMap<Byte, String>();
static StringBuilder stringBuilder = new StringBuilder();
public static void main(String[] args) {
String content = "i like like like java do you like a java";
System.out.println("content = " + content);
byte[] bytes = content.getBytes();
System.out.println("bytes = " + bytes.length);
byte[] huffmanZip = huffmanZip(bytes);
System.out.println("huffmanZip = " + Arrays.toString(huffmanZip));
System.out.println("huffmanZip.length = " + huffmanZip.length);
/**
* 解码
*/
byte[] sourceBytes = decode(huffmanCodes, huffmanZip);
System.out.println("sourceBytes = " + new String(sourceBytes));
/**
* 压缩文件
*/
String srcFile = "d://test-1.bmp";
String dstFile = "d://test-1.zip";
zipFile(srcFile, dstFile);
System.out.println("文件压缩成功");
/**
* 解压文件
* TODO 解压后的文件不能打开
*/
String zipFile = "d://test-1.zip";
String dstFiles = "d://test-2.bmp";
unZipFile(zipFile, dstFiles);
System.out.println("解压完成");
/*
List<Node> nodes = getNodes(bytes);
System.out.println("nodes = " + nodes);
System.out.println("霍夫曼树--前序遍历");
Node huffmanTreeRoot = createHuffmanTree(nodes);
huffmanTreeRoot.preOrder();
//测试生成了对应的霍夫曼编码
getCodes(huffmanTreeRoot);
System.out.println("huffmanCodes = " + huffmanCodes);
byte[] zip = zip(bytes, huffmanCodes);
//zip = [-88, -65, -56, -65, -56, -65, -55, 77, -57, 6, -24, -14, -117, -4, -60, -90, 28]
System.out.println("zip = " + Arrays.toString(zip));
*/
}
/**
* 文件解压
*
* @param zipFile 待解压的文件
* @param dstFile 解压后的文件存储位置
*/
public static void unZipFile(String zipFile, String dstFile) {
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
try {
is = new FileInputStream(zipFile);
ois = new ObjectInputStream(is);
byte[] huffmanBytes = (byte[]) ois.readObject();
Map<Byte, String> huffmanCodes = (Map<Byte, String>) ois.readObject();
//解码
byte[] decodes = decode(huffmanCodes, huffmanBytes);
//将decodes写入文件
os = new FileOutputStream(dstFile);
os.write(decodes);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
//与打开顺序相反
if (os != null) {
os.close();
}
if (ois != null) {
ois.close();
}
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 将一个文件进行压缩
*
* @param srcFile 待压缩的文件路径
* @param dstFile 压缩后的文件存储位置
*/
public static void zipFile(String srcFile, String dstFile) {
FileInputStream fis = null;
OutputStream os = null;
ObjectOutputStream oos = null;
try {
fis = new FileInputStream(srcFile);
//创建一个与原文件大小一样的byte[]
byte[] bytes = new byte[fis.available()];
//读取文件
fis.read(bytes);
//获取文件对应的霍夫曼编码表
byte[] huffmanZipBytes = huffmanZip(bytes);
os = new FileOutputStream(dstFile);
//创建一个与文件输出流关联的ObjectOutputStream
oos = new ObjectOutputStream(os);
//以对象流的方式写入霍夫曼编码
oos.writeObject(huffmanZipBytes);
//这里我们以对象流的方式写入 赫夫曼编码,是为了以后我们恢复源文件时使用
//注意一定要把赫夫曼编码 写入压缩文件
oos.writeObject(huffmanCodes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (oos != null) {
oos.close();
}
if (os != null) {
os.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @param huffmanCodes 霍夫曼编码表map
* @param huffmanBytes 霍夫曼编码得到的字节数组
* @return
*/
private static byte[] decode(Map<Byte, String> huffmanCodes, byte[] huffmanBytes) {
//1.先得到huffmanBytes对应的二进制的字符串
StringBuilder stringBuilder = new StringBuilder();
//将byte数组转成二进制的字符串
for (int i = 0; i < huffmanBytes.length; i++) {
byte b = huffmanBytes[i];
//判读是否最后1个字节
boolean flag = (i == huffmanBytes.length - 1);
stringBuilder.append(byteToBitString(!flag, b));
}
//System.out.println("stringBuilder = " + stringBuilder.toString());
//把字符串按照指定的霍夫曼编码进行解码
Map<String, Byte> map = new HashMap<>();
for (Map.Entry<Byte, String> entry : huffmanCodes.entrySet()) {
map.put(entry.getValue(), entry.getKey());
}
//System.out.println("map = " + map);
//创建集合,存放byte
ArrayList<Byte> list = new ArrayList<>();
for (int i = 0; i < stringBuilder.length(); ) {
int count = 1;
boolean flag = true;
Byte b = null;
while (flag) {
/**
* TODO 解压时StringIndexOutOfBoundsException: String index out of range: 64587
* Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 64587
* at java.lang.AbstractStringBuilder.substring(AbstractStringBuilder.java:933)
* at java.lang.StringBuilder.substring(StringBuilder.java:76)
* at com.atguigu.huffmancode.HuffmanCode.decode(HuffmanCode.java:212)
* at com.atguigu.huffmancode.HuffmanCode.unZipFile(HuffmanCode.java:92)
* at com.atguigu.huffmancode.HuffmanCode.main(HuffmanCode.java:48)
*/
String key = stringBuilder.substring(i, i + count);
b = map.get(key);
if (b == null) {
count++;
} else {
//匹配到
flag = false;
}
}
list.add(b);
//i移动到count位置
i += count;
}
//把list中的数据放到byte[]中
byte[] bytes = new byte[list.size()];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = list.get(i);
}
return bytes;
}
/**
* 将一个byte转换成一个二进制的字符串
*
* @param flag 标志是否需要补高位;如true则需要补高位
* @param b 传入的byte
* @return b对应的二进制字符串(补码返回)
*/
private static String byteToBitString(boolean flag, byte b) {
int temp = b;
//如果是正数,须补高位
//按位
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
算法与数据结构涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
资源推荐
资源详情
资源评论
收起资源包目录
【尚硅谷】数据结构与算法(Java数据结构与算法).zip (44个子文件)
open_suanfayushujujiegouxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcxxxxxxxxxxxxcxvcvcv
Algorithm
src
com
atguigu
greedy
GreedyAlgorithm.java 3KB
kmp
ViolenceMatch.java 1KB
KmpAlgorithm.java 2KB
dac
Hanoitower.java 790B
binarysearchnorecursion
BinarySearchNoRecursion.java 800B
Algorithm.iml 423B
.idea
misc.xml 258B
inspectionProfiles
Project_Default.xml 2KB
modules.xml 419B
.gitignore 272B
encodings.xml 238B
.gitignore 29B
DataStructures
src
com
atguigu
sort
InsertSort.java 2KB
SelectSort.java 3KB
QuickSort.java 3KB
RadixSort.java 8KB
ShellSort.java 4KB
BubbleSort.java 4KB
MergeSort.java 3KB
tree
HeapSort.java 3KB
BinaryTreeDemo.java 9KB
ArrBinaryTreeDemo.java 2KB
huffmantree
HuffmanTree.java 3KB
linkedlist
DoubleLinkedListDemo.java 9KB
Josephu.java 4KB
SingleLinkedListDemo.java 9KB
huffmancode
HuffmanCode.java 14KB
stack
Calculator.java 6KB
ArrayStackDemo.java 3KB
PolandNotation.java 7KB
binarysorttree
BinarySortTreeDemo.java 9KB
queue
ArrayQueueDemo.java 4KB
CircleQueueDemo.java 5KB
avl
AvlTreeDemo.java 11KB
search
FibonacciSearch.java 3KB
BinarySearch.java 3KB
InsertValueSearch.java 1KB
SeqSearch.java 704B
hashtab
HashTabDemo.java 5KB
recursion
EightQueens.java 2KB
MiGong.java 4KB
test
HuffmanTreeTest.java 3KB
sparsearray
SparseArray.java 3KB
DataStructures.iml 423B
共 44 条
- 1
资源评论
极致人生-010
- 粉丝: 4379
- 资源: 3086
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功