Introdução ao período de fundação
O período de construção da fundação descreve principalmente os princípios necessários para compressão e descompressão, principalmente descrição de texto e uma pequena quantidade de análise de imagem.
Forneça o código completo, você pode usar o espaço do blogger diretamente sem aprender https://blog.csdn.net/JOElib?spm=1011.2266.3001.5343Algoritmo de pesquisa de Qianggehttps: //blog.csdn.net/JOElib/article/details/123848806 ?spm=1001.2014.3001.5501
Visão geral da definição
caminho
caminho
O caminho é como ir do nó raiz ao nó de destino, e o processo no meio é chamado de caminho
o comprimento do caminho
O comprimento do caminho é o número de nós experimentados no meio do processo de caminhada, por exemplo, o comprimento do caminho do nó na camada L é L-1.
peso do nó
O peso de um nó é um número que recebe um significado especial no nó, e esse número é chamado de peso do nó.
comprimento do caminho ponderado
O peso do nó é multiplicado pelo tamanho do caminho do nó, e o produto é chamado de caminho ponderado
comprimento do caminho ponderado da árvore
O caminho ponderado da árvore representa a soma dos caminhos ponderados de todos os nós folha, e é chamado de caminho ponderado da árvore. A abreviação do caminho ponderado da árvore é WPL
árvore de Huffman
A árvore de Huffman é um tipo especial de árvore binária. Essa árvore binária possui o menor WPL, ou seja, a árvore binária com o menor caminho ponderado da árvore é chamada de árvore de Huffman. Sua característica é que quanto maior o peso, mais próximo o nó é.
método de armazenamento
Codificação de comprimento fixo
Tomando uma string como exemplo, de acordo com o complemento de dois correspondente ao código ASCII de cada caractere, ela é armazenada intacta, o que é chamado de codificação de comprimento fixo.
codificação de comprimento variável
Tomando uma string como exemplo, primeiro conte o número de elementos que aparecem em cada caractere nela, classifique-os primeiro e, de acordo com a ordem de classificação, escreva um código binário menor para o ASCII maior e use esses códigos para armazenar
Desvantagem: A leitura do código produzirá discrepâncias, como os códigos 01 e 011, seus dois prefixos são iguais e são lidos um a um. Suponha que queremos 011, o sistema pode ler 01
codificação de prefixo
Codificação de prefixo, ou seja, o prefixo de cada codificação de comprimento variável é diferente, o que pode evitar as deficiências mencionadas acima de divergência na leitura
Codificação de Huffman
A codificação Huffman é uma codificação de prefixo especial, e a codificação Huffman correspondente é obtida de acordo com o caminho
código completo
package datastructure.chapter04.tree.huffman.huffmancoding;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 江骏杰
* Date: 2022-03-29
* Time: 21:38
*/
public class Node implements Comparable<Node> {
public Byte ascii;
public int value;
public Node left;
public Node right;
public Node(Byte ascii,int value) {
this.ascii = ascii;
this.value = value;
}
public String toString() {
return "Node[ascii = " + ascii + " value = " + value + "]";
}
public int compareTo(Node node) {
return value - node.value;
}
}
package datastructure.chapter04.tree.huffman.huffmancoding;
import java.io.*;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 江骏杰
* Date: 2022-03-29
* Time: 21:37
*/
public class HuffmanCode implements Serializable {
@Serial
private static final long serialVersionUID = 4420;
private static final HashMap<Byte,String> HUFFMAN_CODES = new HashMap<>();
private static final StringBuffer STRING_BUFFER = new StringBuffer();
private static int lastCount;
public static byte[] huffmanCodeZip(String s) {
var content = s.getBytes();
var list = getNodes(content);
var huffmanTreeRoot = createHuffmanTree(list);
getCodes(huffmanTreeRoot,"",STRING_BUFFER);
return zip(content,HUFFMAN_CODES);
}
public static byte[] huffmanCodeZip(byte[] content) {
var list = getNodes(content);
var huffmanTreeRoot = createHuffmanTree(list);
getCodes(huffmanTreeRoot,"",STRING_BUFFER);
return zip(content,HUFFMAN_CODES);
}
public static List<Node> getNodes(byte[] content) {
var map = new HashMap<Byte,Integer>();
var list = new ArrayList<Node>();
for (var item : content) {
var count = map.get(item);
if (count == null) {
map.put(item,1);
}else {
map.put(item,++count);
}
}
for (var entry : map.entrySet()) {
list.add(new Node(entry.getKey(),entry.getValue()));
}
return list;
}
public static Node createHuffmanTree(List<Node> list) {
while (list.size() > 1) {
Collections.sort(list);
var leftNode = list.get(0);
var rightNode = list.get(1);
var parentNode = new Node(null, leftNode.value + rightNode.value);
parentNode.left = leftNode;
parentNode.right = rightNode;
list.add(parentNode);
list.remove(1);
list.remove(0);
}
return list.get(0);
}
public static void getCodes(Node node,String code,StringBuffer strBuf) {
var curStrBuf = new StringBuffer(strBuf);
curStrBuf.append(code);
if (node != null) {
if (node.ascii == null) {
getCodes(node.left,"0",curStrBuf);
getCodes(node.right,"1",curStrBuf);
}else {
HUFFMAN_CODES.put(node.ascii,curStrBuf.toString());
}
}
}
public static byte[] zip(byte[] content,Map<Byte,String> huffmanCodes) {
var strBuf = new StringBuilder();
for (var item : content) {
strBuf.append(huffmanCodes.get(item));
}
var len = (strBuf.length() + 7) / 8;
var huffmanCodesBytes = new byte[len];
String str;
var index = 0;
for (int i = 0; i < strBuf.length(); i+= 8) {
if (i + 8 < strBuf.length()) {
str = strBuf.substring(i,i+8);
}else {
str = strBuf.substring(i);
lastCount = str.length();
}
huffmanCodesBytes[index++] = (byte) Integer.parseInt(str,2);
}
return huffmanCodesBytes;
}
public static String byteToString(byte b,boolean flag) {
int temp = b;
temp |= 256;
String str = Integer.toBinaryString(temp);
if (flag) {
return str.substring(str.length() - 8);
}
return str.substring(str.length() - lastCount);
}
public static byte[] decode(byte[] huffmanCodesBytes,Map<Byte,String> huffmanCodes) {
var strBil = new StringBuilder();
for (int i = 0; i < huffmanCodesBytes.length; i++) {
boolean flag = (i != huffmanCodesBytes.length -1);
strBil.append(byteToString(huffmanCodesBytes[i],flag));
}
var map = new HashMap<String,Byte>();
for (var entry : huffmanCodes.entrySet()) {
map.put(entry.getValue(),entry.getKey());
}
var list = new ArrayList<Byte>();
for (int i = 0; i < strBil.length();) {
Byte b ;
var count = 1;
while ((b = map.get(strBil.substring(i, i + count))) == null) {
count++;
}
list.add(b);
i += count;
}
var content = new byte[list.size()];
for (int i = 0; i < content.length; i++) {
content[i] =list.get(i);
}
return content;
}
public static String decode(byte[] huffmanBytes) {
return new String(decode(huffmanBytes,HUFFMAN_CODES));
}
public static void fileZip(String srcPath,String desPath) {
try(var fis = new FileInputStream(srcPath);
var fos = new FileOutputStream(desPath);
var oos = new ObjectOutputStream(fos)
) {
var content = new byte[fis.available()];
fis.read(content);
byte[] huffmanBytes = huffmanCodeZip(content);
oos.writeObject(huffmanBytes);
oos.writeObject(HUFFMAN_CODES);
oos.writeObject(lastCount);
oos.flush();
fos.flush();
}catch (Exception e) {
e.printStackTrace();
}
}
public static void fileDeZip(String zipPath,String desPath) {
try(var fis = new FileInputStream(zipPath);
var ois = new ObjectInputStream(fis);
var fos = new FileOutputStream(desPath)
) {
var huffmanBytes = (byte[])ois.readObject();
var huffmanCodes = (Map<Byte,String >)ois.readObject();
lastCount = (int)ois.readObject();
var content = decode(huffmanBytes,huffmanCodes);
fos.write(content);
fos.flush();
}catch (Exception e) {
e.printStackTrace();
}
}
}
para concluir
Para completar um código, devemos primeiro entender seu princípio. Através deste princípio, podemos espionar um ou dois
No próximo artigo, começaremos a criar árvores de Huffman