赫夫曼编码及解码
package com.example.dataalgorithm.tree;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class huffmanCode {
public static void main(String[] args) {
String str = "i like like like java do you like a java";
byte[] contentBytes = str.getBytes();
byte[] bytes = huffmanZip(contentBytes);
System.out.println(Arrays.toString(bytes));
byte[] decode = decode(huffmanCodes, bytes);
System.out.println("原来的字符串:"+ new String(decode));
}
private static byte[] decode(Map<Byte,String> huffmanCodes,byte[] huffmanBytes){
StringBuilder stringBuilder = new StringBuilder();
for (int i=0;i< huffmanBytes.length; i++){
boolean flag = (i == huffmanBytes.length -1);
stringBuilder.append(byteToBitString(!flag,huffmanBytes[i]));
}
Map<String,Byte> map = new HashMap<>();
for (Map.Entry<Byte,String> entry : huffmanCodes.entrySet()){
map.put(entry.getValue(),entry.getKey());
}
List<Byte> list = new ArrayList<>();
for (int i=0;i<stringBuilder.length();){
int count =1;
boolean flag = true;
Byte b = null;
while (flag){
String key = stringBuilder.substring(i, i + count);
b = map.get(key);
if(null == b){
count ++;
}else{
flag = false;
}
}
list.add(b);
i += count;
}
byte[] b = new byte[list.size()];
for (int i=0;i<b.length;i++){
b[i] = list.get(i);
}
return b;
}
private static String byteToBitString(boolean flag,byte b){
int temp = b;
if(flag){
temp |= 256;
}
String str = Integer.toBinaryString(temp);
if(flag){
return str.substring(str.length() - 8);
}else{
return str;
}
};
private static byte[] huffmanZip(byte[] bytes){
List<Node> nodes = getNodes(bytes);
Node huffmanTree = createHuffmanTree(nodes);
getCodes(huffmanTree,"",stringBuilder);
return zip(bytes, huffmanCodes);
}
public static Map<Byte,String> huffmanCodes = new HashMap<>();
public static StringBuilder stringBuilder = new StringBuilder();
private static byte[] zip(byte[] bytes,Map<Byte,String> huffmanCodes){
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes){
stringBuilder.append(huffmanCodes.get(b));
}
System.out.println(stringBuilder);
int len;
if(stringBuilder.length() % 8 == 0){
len = stringBuilder.length() / 8;
}else{
len = stringBuilder.length() / 8 + 1;
}
byte[] huffmanCodeBytes = new byte[len];
int index = 0;
for (int i=0;i<stringBuilder.length();i+=8){
String strByte;
if(i+8>stringBuilder.length()){
strByte = stringBuilder.substring(i);
}else{
strByte = stringBuilder.substring(i,i+8);
}
huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte,2);
index++;
}
return huffmanCodeBytes;
}
private static void getCodes(Node node,String code,StringBuilder stringBuilder){
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(code);
if (null != node){
if(null == node.data){
getCodes(node.left,"0",stringBuilder2);
getCodes(node.right,"1",stringBuilder2);
}
else {
huffmanCodes.put(node.data,stringBuilder2.toString());
}
}
}
private static @NotNull List<Node> getNodes(byte @NotNull [] bytes){
List<Node> nodes = new ArrayList<>();
Map<Byte,Integer> counts = new HashMap<>();
for (byte b : bytes) {
counts.merge(b, 1, Integer::sum);
}
for (Map.Entry<Byte,Integer> entry : counts.entrySet()){
nodes.add(new Node(entry.getKey(),entry.getValue()));
}
return nodes;
}
private static Node createHuffmanTree(@NotNull List<Node> nodes){
while (nodes.size() > 1){
Collections.sort(nodes);
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parent = new Node(null,leftNode.weight + rightNode.weight);
parent.left = leftNode;
parent.right = rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
return nodes.get(0);
}
}
class Node implements Comparable<Node>{
Byte data;
int weight;
Node left;
Node right;
public Node(Byte data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(Node o) {
return this.weight - o.weight;
}
@Override
public String toString() {
return "Node[ data="+data+",weight="+weight+"]";
}
public void preOrder(){
System.out.println(this);
if(null != this.left){
this.left.preOrder();
}
if(null != this.right){
this.right.preOrder();
}
}
}
赫夫曼解压及压缩案例
package com.example.dataalgorithm.tree;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.util.*;
public class huffmanCode {
public static void main(String[] args) {
String dstFile = "D://stu-git//数据结构与算法//cs//ddd01.png";
String zipFile = "D://stu-git//数据结构与算法//cs//ddd.zip";
unZipFile(zipFile,dstFile);
}
public static void unZipFile(String zipFileName,String distFile){
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
try {
is = new FileInputStream(zipFileName);
ois = new ObjectInputStream(is);
byte[] huffmanBytes = (byte[]) ois.readObject();
Map<Byte,String> codes = (Map<Byte, String>) ois.readObject();
byte[] decode = decode(codes, huffmanBytes);
os = new FileOutputStream(distFile);
os.write(decode);
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(null != os){
os.close();
}
if(null != is){
is.close();
}
if(null != ois){
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void zipFile(String srcFile,String dstFile){
OutputStream os = null;
ObjectOutputStream oos = null;
FileInputStream is = null;
try {
is = new FileInputStream(srcFile);
new ObjectInputStream(is);
byte[] b = new byte[is.available()];
is.read(b);
System.out.println(b.length);
byte[] huffmanBytes = huffmanZip(b);
System.out.println(huffmanBytes.length);
os = new FileOutputStream(dstFile);
oos = new ObjectOutputStream(os);
oos.writeObject(huffmanBytes);
oos.writeObject(huffmanCodes);
System.out.println("文件压缩完成~~");
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(null != is){
is.close();
}
if(null != os){
os.close();
}
if(null != oos){
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static byte[] decode(Map<Byte,String> huffmanCodes,byte[] huffmanBytes){
StringBuilder stringBuilder = new StringBuilder();
for (int i=0;i< huffmanBytes.length; i++){
boolean flag = (i == huffmanBytes.length -1);
stringBuilder.append(byteToBitString(!flag,huffmanBytes[i]));
}
Map<String,Byte> map = new HashMap<>();
for (Map.Entry<Byte,String> entry : huffmanCodes.entrySet()){
map.put(entry.getValue(),entry.getKey());
}
List<Byte> list = new ArrayList<>();
for (int i=0;i<stringBuilder.length();){
int count =1;
boolean flag = false;
Byte b ;
while (true){
String key = "";
if(stringBuilder.length()- i > 8){
key = stringBuilder.substring(i, i + count);
}else {
key = stringBuilder.substring(stringBuilder.length() - count);
flag = true;
}
b = map.get(key);
if(null == b){
count ++;
}else {
list.add(b);
break;
}
}
i += count;
if(flag){
break;
}
}
byte[] b = new byte[list.size()];
for (int i=0;i<b.length;i++){
b[i] = list.get(i);
}
return b;
}
private static String byteToBitString(boolean flag,byte b){
int temp = b;
if(flag){
temp |= 256;
}
String str = Integer.toBinaryString(temp);
if(flag){
return str.substring(str.length() - 8);
}else{
return str;
}
};
private static byte[] huffmanZip(byte[] bytes){
List<Node> nodes = getNodes(bytes);
Node huffmanTree = createHuffmanTree(nodes);
getCodes(huffmanTree,"",stringBuilder);
return zip(bytes, huffmanCodes);
}
public static Map<Byte,String> huffmanCodes = new HashMap<>();
public static StringBuilder stringBuilder = new StringBuilder();
private static byte[] zip(byte[] bytes,Map<Byte,String> huffmanCodes){
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes){
stringBuilder.append(huffmanCodes.get(b));
}
int len;
if(stringBuilder.length() % 8 == 0){
len = stringBuilder.length() / 8;
}else{
len = stringBuilder.length() / 8 + 1;
}
byte[] huffmanCodeBytes = new byte[len];
int index = 0;
for (int i=0;i<stringBuilder.length();i+=8){
String strByte;
if(i+8>stringBuilder.length()){
strByte = stringBuilder.substring(i);
}else{
strByte = stringBuilder.substring(i,i+8);
}
huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte,2);
index++;
}
return huffmanCodeBytes;
}
private static void getCodes(Node node,String code,StringBuilder stringBuilder){
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(code);
if (null != node){
if(null == node.data){
getCodes(node.left,"0",stringBuilder2);
getCodes(node.right,"1",stringBuilder2);
}
else {
huffmanCodes.put(node.data,stringBuilder2.toString());
}
}
}
private static @NotNull List<Node> getNodes(byte @NotNull [] bytes){
List<Node> nodes = new ArrayList<>();
Map<Byte,Integer> counts = new HashMap<>();
for (byte b : bytes) {
counts.merge(b, 1, Integer::sum);
}
for (Map.Entry<Byte,Integer> entry : counts.entrySet()){
nodes.add(new Node(entry.getKey(),entry.getValue()));
}
return nodes;
}
private static Node createHuffmanTree(@NotNull List<Node> nodes){
while (nodes.size() > 1){
Collections.sort(nodes);
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parent = new Node(null,leftNode.weight + rightNode.weight);
parent.left = leftNode;
parent.right = rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
return nodes.get(0);
}
}
class Node implements Comparable<Node>{
Byte data;
int weight;
Node left;
Node right;
public Node(Byte data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(Node o) {
return this.weight - o.weight;
}
@Override
public String toString() {
return "Node[ data="+data+",weight="+weight+"]";
}
public void preOrder(){
System.out.println(this);
if(null != this.left){
this.left.preOrder();
}
if(null != this.right){
this.right.preOrder();
}
}
}
|