Entry
áá á¡á¢áá¢ááášá ááá¡áá£áá áá á°áá€ááááá¡ áªááááá ááááá ááááá, áá¡ááá ááá¡ ááááá§ááááááá áááááªáááá ášááá£áášááá¡áá¡.
ášáááááá, á©ááá áááá¬áá á ááá á¢áá áá á¥ááá¡. áá¡ á£ááá áá§á , áááá áá áá áá¥á¢ááá£áá áááá®áá áªááááááá¡ ááá áášá. áááááááá á ááá¡á¢áá¡ áááá áá£áá ááá¡ááá ááŠááá£ááá á¡ááááá¡ áááááá£á¢áá á£áá áááªáááá áááá¡ áááááááááááááá áá á áááá ᢠááá€áá áá¢áá¡ á¬ááááááá âáááááªáááá á¡á¢á á£á¥á¢á£á ááá áá ááááá áááááá á¯áááášáâ. áá¡á á áá, á§ááááá€áá á áááá áááá!
ááá¢áá á áááá áááá
á©ááá£áááá áá á¢áá¥á¡á¢á£á á€áááášá áá áá á¡áááááá ááášáá€á á£ááá 8 ááá¢áá (ASCII ááááá ááá) áá 16 (Unicode ááááá ááá). ášáááááá, áááááá®ááááá ASCII ááááá áááá¡. ááááááááá, áááŠáá á¡á¢á áá¥ááá s1 = "SUSIE SAYS IT IS EASYn". á¡ááá áá á¯ááášá, á¡á¢á áá¥ááášá 22 á¡ááááááá, á á áá¥áá á£ááá, ááá¢áá ááááá¡ áá áá®ááá á®áááá¡ á¡ááááááá¡ á©áááááá - 'n'. áá á®áááá¡ ášáááªáááá á€áááá áá¬áááá¡ 22*8 = 176 ááá¢á¡. ááášáááá á©ááááá áááá®áá: áá áá¡ áᣠáá á á ááªáááááá£á á 8 ááá¢áá¡ ááááá§ááááá 1 á¡ááááááá¡ ááášáá€áá áá¡áááá¡? á©ááá áá ááá§ááááá á§áááá ASCII á¡ááááááá¡. ááášááá᪠áá, áᣠáá¡ááá á§áá€áááá§áááá, á£á€á á á ááªáááááá£á á áá¥áááááá, ááááªáá á§áááááá á®ášáá á áá¡á - S - á§áááááá ááááá áááá, á®ááá á£áášáááááá¡á áá¡áá¡áááá¡ - T (áá U, áá 'n') - á£á€á á áááááá¢á£á á áááá. áá¡ áá áá¡ á°áá€ááááá¡ ááááá áááá: áá¥ááá á£ááá áááááá á¡áá£ááááá¡á ááááá áááá¡ ááá áááá¢á, á ááááášá᪠á€áááá áá¥áááá áááááááá£á á á¬áááá¡. á¡ááá¡áááá ááá áááá£á áá, á áá á¡á®ááááá¡á®áá á¡ááááááá¡ áá¥áááá á¡á®ááááá¡á®áá ááááá¡ á¡ááá á«á - áá¡ áá áá¡ ááááá ááááá¡ á¡áá€á£á«áááá.
ááááá ááá
á áá¢áá áá ááááªáá á¡ááááááá¡ 'S' áááá, ááááááááá, 1 ááá¢áááá: 0 áá 1. ááááá áá§áá¡ 1. ášááááá áááá á á§áááááá áááá áªááááá£áá á¡áááááá - ' ' (á¡ááá áªá) - ááááªááá 0-á¡. á¬áá ááááááááá, áá¥ááá áááá¬á§áá ááášáá€á áá áá¥áááá ášáá¢á§ááááááá - ááášáá€á á£áá á¡á¢á áá¥ááá s1 - áá á®ááááá, á áá áááá áá¬á§ááá 1-áá. áááš, á á á£ááá áááááááá: áá áá¡ á¡áááááá S, áᣠá¡á®áá á¡áááááá, ááááááááá A? áá¥áááá áááááááááá á, á©ááááá áááášááááááááá á¬áá¡á:
áá áªáá áá áááá áá á£ááá áá§áá¡ á¡á®áá áá áá€áá¥á¡á
áá¡ á¬áá¡á áá áá¡ ááááá ááááá¡ ááá¡ááŠááá. ááá áááá, ááááá¡ ášáá¥ááá áá¬á§ááá á¡áá®ášáá áá¡ áªá®á áááá, á ááááá᪠ááá£áááááá¡ áááááá£áá á¡ááááááá¡ á¡áá®ášáá ááá (ášáááá®ááááááá¡ á áááááááááá):
á§áááááá ááá¢á áááááááá¡ áá¥ááá á¡ááááááááá á£ááá áá§áá¡ ááááá ááá£áá á§áááááá áááááááá ášáá¡áá«ááááááá ááá¢áááá¡ á áááááááá. áá ááááªáá áá á-áá áá ášáá¡áá«áá ááááá¡ áªá®á áááá¡ áááááááá¡:
áá¡á á áá, ááááá ááá£áá ášáá¢á§ááááááá áá¡á áááááá§á£á ááá:
10 01111 10 110 1111 00 10 010 1110 10 00 110 0110 00 110 10 00 1111 010 10 1110 01110
áááááá£áá á¡ááááááá¡ áááá áááááá§ááá ááá¢áá ááááá. áá¡ ááááááááá áá ááá®áááá ášááá£áášá£á á€áááášá!
á©ááááá áááá®áá: á áááá áááá€áá¥á á áá áá®áááááá ááááá á áááá ášáá¥áááá¡ ááááá¡ áªá®á ááá? áá¡ á¥ááááá áá¥áááá áááá®ááá£áá.
á°áá€ááááá¡ á®áá¡ áášááááá
áá¡ áá áá¡ á¡ááá᪠ááááá á£áá á¡áá«áááá á®áááá áááááá á¡áááášááááášá. áá áááá ááá£ááá, áᥠáá áááááá ááááá á«ááááá¡, á©áá¡ááá¡ áá á¬áášááá¡ áááááááá. áᥠáá áá¡ á®áá¡ á¡á¢á á£á¥á¢á£á á á¯áááášá:
public class Node {
private int frequence;
private char letter;
private Node leftChild;
private Node rightChild;
...
}
class BinaryTree {
private Node root;
public BinaryTree() {
root = new Node();
}
public BinaryTree(Node root) {
this.root = root;
}
...
}
áá¡ áá áá áá¡ á¡á á£áá áááá, á¡á á£áá áááá áá¥áááá á¥ááááá.
áᥠáá áá¡ ááááá áááá á®áá¡ áá¡áášááááááá:
- ášáá¥ááááá Node ááááá¥á¢á ášáá¢á§áááááááááááá áááááá£áá á¡ááááááá¡áááá¡ (á¡á¢á áá¥ááá s1). á©áááá¡ ášáááá®ááááášá, áá¥áááá 9 ááááá«á (Node ááááá¥á¢ááá). áááááá£áá ááááá«á ášáááááá áá á áááááªáááá ááááá¡áááá: á¡áááááá áá á¡áá®ášáá á
- ášáá¥ááááá á®áá¡ ááááá¥á¢á (BinaryTree) áááááá£áá ááááá«áá¡ ááááá«áá¡áááá¡. ááááá«á á®áááá á®áá¡ á€áá¡áá.
- á©áááá áá¡ á®áááá áá ááá áá¢áá¢á£á á ááášá. á á᪠á£á€á á ááááááá á¡áá®ášáá á, ááá á£á€á á áááŠáááá áá ááá áá¢áá¢á. ááá áááá, ááááááááá¡áá¡ á§áááááááá¡ ášááá á©ááá á§áááááá áááááá á¡áá®ášáá áá¡ á®á.
ášáááááá, áá¥ááá á£ááá áááááááá áªáááá£á áá ášáááááá:
- áááááŠáá áá á á®á áá ááá áá¢áá¢á£áá á áááááá áá ááá®áááá áá¡ááá áá®ááá ááááá«áá¡ ášááááááá (áá®ááá ášáá¥ááááá ááááá«á áá¡áá¡ ááá áášá). áá®ááá ááááá«áá¡ á¡áá®ášáá á á£áá áá¡ áá á ášáááááááááá á®áá¡ á¡áá®ášáá ááááá¡ á¯ááá¡.
- áá ááááá«áá¡áááá¡ ášáá¥ááááá áá ááááá«áá ááá€á£á«áááá£áá á®á. á©áááá áá¡ á®á áá¡áá áá ááá áá¢áá¢á£á á ááášá. (á ááááá á®áá¡ áá®ááá á¡áá®ášáá á áá¥áá¡, áá¡ á¡áááá áá£ááá áá®áá ááááááá ááá®ááááá á ááášá)
- ááááá á«áááá 1 áá 2 ááááá¯ááá, á¡áááá á ááášá áá ááá á©ááá áá áá á®á - á°áá€ááááá¡ á®á
áááááá®áááá áá¡ ááááá áááá á¡á¢á áá¥áááá s1:

áᥠá¡áááááá "lf" (linefeed) ááŠááášáááá¡ áá®áá á®ááá¡, "sp" (á¡ááá áªá) áá áá¡ á¡ááá áªá.
á á áá áá¡ ášáááááá?
á©ááá áááááŠáá á°áá€ááááá¡ á®á. á²á²á² á²á². áá á á áá£á§áá ááá¡? áá¡ááá áááá¡ á£á€áá¡áá áá ááááŠáááá áá ášááááá, áá¥ááá á£ááá ááááá áá á§áááá ášáá¡áá«áá áááááá á€áá¡ááááá á®áá¡ á€ááááááááá. á©ááá áááááá®ááááá, á áá ááááá¬áá áá 0-áá¡ ááááá¡, áᣠáá¡ áááá§áááá á ááá áªá®ááá ášáááááá áá 1, áᣠáá¡ áááá§áááá á ááá á¯áááá. ááááªá áá á áá ááá¥ááá, áá ááŠááášááááášá, á¡ááááááá¡ áááá áá áá¡ ááá á®áá¡ á€áá¡ááááá á€ááááááá, á ááááá᪠ášáááªááá¡ ááááá á¡ááááááá¡.

ááá áááá, ááááááá¡ áªá®á ááá ááŠááá©ááá. ááááááááá¡á¬áááá, á áá áᣠáááááááááá¡á¬ááááá áá áªá®á ááá¡, ášááááá«ááá ááááá¡ááááá áááááá£áá á¡ááááááá¡ "á¬ááááá" - áá¡ áá áá¡ ááá¡á ááááá¡ á¡ááá á«á. ášááááá, ášááá£áášá£áá á€áá ááá, á¬á§áá áá¡ á€áááá áá¬áááá¡: 2 * 3 + 2 * 4 + 3 * 3 + 6 * 2 + 1 * 4 + 1 * 5 + 2 * 4 + 4 * 2 + 1 * 5 = 65 ááá¢á . ááááááá áá¬ááááá 176 ááá¢á¡. áááá¢áá, á©ááá ášáááááªáá áá áá¡ 176/65 = 2.7-á¯áá ! áááá áá áá¡ á£á¢ááááá. áá¡ááá ááááá€áá áááá áááááááá á¡áááá áá£ááá. á áá¢áá? ááááá áªáá¢á ááááááááááá áá¥áááá áááá®ááá£áá.
ááááááá ááá
áá¡á, ááááá á§áááááá ááá á¢ááá á áá áá áá¡ ááášáá€áá á. áá€áá¥á áá, áááá áá áá¥áááááááá ááááááªáááá, á áá ášááá£áášá£áá á€ááááá¡ ášáá¥ááá ášáá£á«ááááááá, á§áááááááá á ááááášááááááá¡ ááá áášá, áᣠá áááá áá§á ááááá ááá£áá - á©ááá ááá ášááá«áááá ááá¡ ááášáá€áá áá¡! áááá®, áááá®, ááááááá áá áááá¡ áááªáááááá ááá, áááá áá áá á£ááá ášááá¥ááá á¢áá¥á¡á¢á£á á á€ááááá¡ table.txt ášááá£áášááá¡ áªá®á áááá:
01110
00
A010
E1111
I110
S10
T0110
U01111
Y1110
áªá®á áááá¡ á©áááá¬áá á á¡áá®áá âá¡ááááááâ âá¡áááááá ááááâ. á áá¢áá áá áá¡ 01110 á¡ááááááá¡ ááá áášá? á¡áááááááááášá, áá¡ áá áá¡ á¡áááááááá, áá®áááá java ááá¡á¢á á£áááá¢áááá, á áááááá¡á᪠ááá§áááá á€áááášá ááááá¢áááá¡áá¡, áá®ááá á®áááá¡ á¡áááááá - 'n' - ááá áááá¥ááááá áá®áá á®áááá (á á᪠áá á£ááá á¡á£áááá£á áá ááŠáá ááá¡). áá¥áááá áááááááááá á, áªáá áááá á®ááá ááááá áá áá¡ á¡áááááá 01110 ááááá¡áááá¡. 00 ááááá¡áááá¡ á¡áááááá áá áá¡ á¡ááá áªá á¡á¢á áá¥áááá¡ ááá¡áá¬á§áá¡ášá. ááá£á§áááááááá á£ááá ááá¥áá, á áá áªá®á áááá¡ ášáááá®ááá¡ áá¡ áááááá ášááá«áááá áá§áá¡ á§áááááá áá ááªáááááá£á á á©áááá á®áááá¡ áááá€ááªáááá¢áá¡áááá¡. áááá áá áááááá ááá¡ááááá áá áááá®áá áªááááááá. ááá®áá á£áá ááá¥áááá ááááá¡áááá áá¥áááá á áááááááááªáááá áááááá¢áá ááášá ááá¢ááááááªááá¡ ášáá¡áá®áá.
áá áªá®á áááá ááá¡á ááášáá€áá á á«ááááá ááááááá. ááááá®á¡áááá á á á¬áá¡áá ááá®áááá«áŠááááááá ááááá áááá¡ ášáá¥áááá¡áá¡:
áá áªáá áá áááá áá á£ááá áá§áá¡ á¡á®áá áá áá€áá¥á¡á
áᥠáá¡ ááááášááá¡ á®ááášááá¬á§áá á ááá¡. á©ááá ááááá®á£áááá ááá¢-ááá¢á áááááááááá áááá áá á áááá ᪠áá áááŠááá£áá á¡á¢á áá¥ááá, á ááááá᪠ášáááááá á¬ááááá®á£áá ááá¢áááá¡áááá, áááá®áááá á¡ááááááá¡ á¡ááááááá¡ ášáá¡áááááá¡ ááášáá€áá áá¡, ááášáááá áááªáá, á áá á¡ááááááá¡ á¡áááááá (áá áá®áááá áá¡!) áá§á ááááá ááá£áá. ášáááááá, á©ááá áá¬áá á á¡ááááááá¡ ááááááá áááá¡ á¡á¢á áá¥áááá (á¡á¢á áá¥ááá, á ááááá᪠ášáááªááá¡ ááááááá ááá£á ášáá¢á§áááááááá¡), ááááááá§ááááá d á¡á¢á áá¥ááá¡ áá ááááá®á£áááá ááášáá€á á£á á€áááá¡ ášááááááášá.
РеалОзаÑОÑ
áá áá ááááááªáá á á©ááá áááá áá á¥áááá¡ ááá¬áá áá. ááááá á¥ááá ááááá áá¡áá á.
á²áááááá ááá¬á§ááá. á£ááá ááááá¡ á§ááááá¡á, á©ááá áá¬áá á Node áááá¡á¡:
public class Node {
private int frequence;//ÑаÑÑПÑа
private char letter;//бÑква
private Node leftChild;//левÑй пПÑПЌПк
private Node rightChild;//пÑавÑй пПÑПЌПк
public Node(char letter, int frequence) { //ÑПбÑÑвеММП, кПМÑÑÑÑкÑПÑ
this.letter = letter;
this.frequence = frequence;
}
public Node() {}//пеÑегÑÑзка кПМÑÑÑÑÑПÑа ÐŽÐ»Ñ Ð±ÐµÐ·ÑÐŒÑММÑÑ
ÑзлПв(ÑÐŒ. вÑÑе в ÑазЎеле П пПÑÑÑПеМОО ЎеÑева ХаÑÑЌаМа)
public void addChild(Node newNode) {//ЎПбавОÑÑ Ð¿ÐŸÑПЌка
if (leftChild == null)//еÑлО левÑй пÑÑÑПй=> пÑавÑй ÑПже=> ЎПбавлÑеЌ в левÑй
leftChild = newNode;
else {
if (leftChild.getFrequence() <= newNode.getFrequence()) //в ПбÑеЌ, левÑÐŒ пПÑПЌкПЌ
rightChild = newNode;//ÑÑÐ°ÐœÐµÑ ÑПÑ, Ñ ÐºÐŸÐ³ÐŸ ЌеМÑÑе ÑаÑÑПÑа
else {
rightChild = leftChild;
leftChild = newNode;
}
}
frequence += newNode.getFrequence();//ОÑÐŸÐ³ÐŸÐ²Ð°Ñ ÑаÑÑПÑа
}
public Node getLeftChild() {
return leftChild;
}
public Node getRightChild() {
return rightChild;
}
public int getFrequence() {
return frequence;
}
public char getLetter() {
return letter;
}
public boolean isLeaf() {//пÑПвеÑка Ма лОÑÑ
return leftChild == null && rightChild == null;
}
}
áá®áá á®á:
class BinaryTree {
private Node root;
public BinaryTree() {
root = new Node();
}
public BinaryTree(Node root) {
this.root = root;
}
public int getFrequence() {
return root.getFrequence();
}
public Node getRoot() {
return root;
}
}
áá ááá áá¢áá¢á£áá á ááá:
import java.util.ArrayList;//Ўа-Ўа, ПÑеÑÐµÐŽÑ Ð±ÑÐŽÐµÑ ÐœÐ° базе ÑпОÑка
class PriorityQueue {
private ArrayList<BinaryTree> data;//ÑпОÑПк ПÑеÑеЎО
private int nElems;//кПл-вП ÑлеЌеМÑПв в ПÑеÑеЎО
public PriorityQueue() {
data = new ArrayList<BinaryTree>();
nElems = 0;
}
public void insert(BinaryTree newTree) {//вÑÑавка
if (nElems == 0)
data.add(newTree);
else {
for (int i = 0; i < nElems; i++) {
if (data.get(i).getFrequence() > newTree.getFrequence()) {//еÑлО ÑаÑÑПÑа вÑÑавлÑеЌПгП ЎеÑева ЌеМÑÑе
data.add(i, newTree);//ÑеЌ ÑаÑÑ. ÑекÑÑегП, ÑП cЎвОгаеЌ вÑе ЎеÑевÑÑ ÐœÐ° пПзОÑОÑÑ
ÑпÑава Ма 1 ÑÑейкÑ
break;//заÑеЌ ÑÑавОЌ МПвПе ЎеÑевП Ма пПзОÑÐžÑ ÑекÑÑегП
}
if (i == nElems - 1)
data.add(newTree);
}
}
nElems++;//ÑвелОÑОваеЌ кПл-вП ÑлеЌеМÑПв Ма 1
}
public BinaryTree remove() {//ÑЎалеМОе Оз ПÑеÑеЎО
BinaryTree tmp = data.get(0);//кПпОÑÑеЌ ÑЎалÑеЌÑй ÑлеЌеМÑ
data.remove(0);//ÑПбÑÑвеММП, ÑЎалÑеЌ
nElems--;//ÑЌеМÑÑаеЌ кПл-вП ÑлеЌеМÑПв Ма 1
return tmp;//вПзвÑаÑаеЌ ÑЎалеММÑй ÑлеЌеМÑ(ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÐœÐ°ÐžÐŒÐµÐœÑÑей ÑаÑÑПÑПй)
}
}
áááá¡á, á ááááá᪠á¥áááá¡ á°áá€ááááá¡ á®áá¡:
public class HuffmanTree {
private final byte ENCODING_TABLE_SIZE = 127;//ЎлОМа кПЎОÑПвПÑМПй ÑаблОÑÑ
private String myString;//ÑППбÑеМОе
private BinaryTree huffmanTree;//ЎеÑевП ХаÑÑЌаМа
private int[] freqArray;//ÑаÑÑПÑÐœÐ°Ñ ÑаблОÑа
private String[] encodingArray;//кПЎОÑПвПÑÐœÐ°Ñ ÑаблОÑа
//----------------constructor----------------------
public HuffmanTree(String newString) {
myString = newString;
freqArray = new int[ENCODING_TABLE_SIZE];
fillFrequenceArray();
huffmanTree = getHuffmanTree();
encodingArray = new String[ENCODING_TABLE_SIZE];
fillEncodingArray(huffmanTree.getRoot(), "", "");
}
//--------------------frequence array------------------------
private void fillFrequenceArray() {
for (int i = 0; i < myString.length(); i++) {
freqArray[(int)myString.charAt(i)]++;
}
}
public int[] getFrequenceArray() {
return freqArray;
}
//------------------------huffman tree creation------------------
private BinaryTree getHuffmanTree() {
PriorityQueue pq = new PriorityQueue();
//алгПÑОÑÐŒ ПпОÑаМ вÑÑе
for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
if (freqArray[i] != 0) {//еÑлО ÑОЌвПл ÑÑÑеÑÑвÑÐµÑ Ð² ÑÑÑПке
Node newNode = new Node((char) i, freqArray[i]);//ÑП ÑПзЎаÑÑ ÐŽÐ»Ñ ÐœÐµÐ³ÐŸ Node
BinaryTree newTree = new BinaryTree(newNode);//а ÐŽÐ»Ñ Node ÑПзЎаÑÑ BinaryTree
pq.insert(newTree);//вÑÑавОÑÑ Ð² ПÑеÑеЎÑ
}
}
while (true) {
BinaryTree tree1 = pq.remove();//ОзвлеÑÑ ÐžÐ· ПÑеÑеЎО пеÑвПе ЎеÑевП.
try {
BinaryTree tree2 = pq.remove();//ОзвлеÑÑ ÐžÐ· ПÑеÑеЎО вÑПÑПе ЎеÑевП
Node newNode = new Node();//ÑПзЎаÑÑ ÐœÐŸÐ²Ñй Node
newNode.addChild(tree1.getRoot());//ÑЎелаÑÑ ÐµÐ³ÐŸ пПÑПЌкаЌО Ўва ОзвлеÑеММÑÑ
ЎеÑева
newNode.addChild(tree2.getRoot());
pq.insert(new BinaryTree(newNode);
} catch (IndexOutOfBoundsException e) {//ПÑÑалПÑÑ ÐŸÐŽÐœÐŸ ЎеÑевП в ПÑеÑеЎО
return tree1;
}
}
}
public BinaryTree getTree() {
return huffmanTree;
}
//-------------------encoding array------------------
void fillEncodingArray(Node node, String codeBefore, String direction) {//запПлМОÑÑ ÐºÐŸÐŽÐžÑПвПÑМÑÑ ÑаблОÑÑ
if (node.isLeaf()) {
encodingArray[(int)node.getLetter()] = codeBefore + direction;
} else {
fillEncodingArray(node.getLeftChild(), codeBefore + direction, "0");
fillEncodingArray(node.getRightChild(), codeBefore + direction, "1");
}
}
String[] getEncodingArray() {
return encodingArray;
}
public void displayEncodingArray() {//ÐŽÐ»Ñ ÐŸÑлаЎкО
fillEncodingArray(huffmanTree.getRoot(), "", "");
System.out.println("======================Encoding table====================");
for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
if (freqArray[i] != 0) {
System.out.print((char)i + " ");
System.out.println(encodingArray[i]);
}
}
System.out.println("========================================================");
}
//-----------------------------------------------------
String getOriginalString() {
return myString;
}
}
áááá¡á, á ááááá᪠ášáááªááá¡ ááášáá€áá áá¡/ááášáá€á ááá¡:
public class HuffmanOperator {
private final byte ENCODING_TABLE_SIZE = 127;//ЎлОМа ÑаблОÑÑ
private HuffmanTree mainHuffmanTree;//ЎеÑевП ХаÑÑЌаМа (ОÑпПлÑзÑеÑÑÑ ÑПлÑкП ÐŽÐ»Ñ ÑжаÑОÑ)
private String myString;//ОÑÑ
ПЎМПе ÑППбÑеМОе
private int[] freqArray;//ÑаÑÑПÑÐ°ÐœÐ°Ñ ÑаблОÑа
private String[] encodingArray;//кПЎОÑПвПÑÐœÐ°Ñ ÑаблОÑа
private double ratio;//кПÑÑÑОÑÐžÐµÐœÑ ÑжаÑОÑ
public HuffmanOperator(HuffmanTree MainHuffmanTree) {//for compress
this.mainHuffmanTree = MainHuffmanTree;
myString = mainHuffmanTree.getOriginalString();
encodingArray = mainHuffmanTree.getEncodingArray();
freqArray = mainHuffmanTree.getFrequenceArray();
}
public HuffmanOperator() {}//for extract;
//---------------------------------------compression-----------------------------------------------------------
private String getCompressedString() {
String compressed = "";
String intermidiate = "";//пÑПЌежÑÑПÑÐœÐ°Ñ ÑÑÑПка(без ЎПбавПÑМÑÑ
МÑлей)
//System.out.println("=============================Compression=======================");
//displayEncodingArray();
for (int i = 0; i < myString.length(); i++) {
intermidiate += encodingArray[myString.charAt(i)];
}
//ÐÑ ÐœÐµ ЌПжеЌ пОÑаÑÑ Ð±ÐžÑ Ð² Ñайл. ÐПÑÑÐŸÐŒÑ ÐœÑжМП ÑЎелаÑÑ ÐŽÐ»ÐžÐœÑ ÑППбÑÐµÐœÐžÑ ÐºÑаÑМПй 8=>
//МÑжМП ЎПбавОÑÑ ÐœÑлО в кПМеÑ(ЌПжМП 1, ÐœÐµÑ ÑазМОÑÑ)
byte counter = 0;//кПлОÑеÑÑвП ЎПбавлеММÑÑ
в ÐºÐŸÐœÐµÑ ÐœÑлей (байÑа в пПлМе Ñ
ваÑОÑ: 0<=counter<8<127)
for (int length = intermidiate.length(), delta = 8 - length % 8;
counter < delta ; counter++) {//delta - кПлОÑеÑÑвП ЎПбавлеММÑÑ
МÑлей
intermidiate += "0";
}
//ÑклеОÑÑ ÐºÐŸÐ»-вП ЎПбавПÑМÑÑ
МÑлей в бОМаÑМПЌ пÑеЎаÑÑвлеМОО О пÑПЌежÑÑПÑМÑÑ ÑÑÑПкÑ
compressed = String.format("%8s", Integer.toBinaryString(counter & 0xff)).replace(" ", "0") + intermidiate;
//ОЎеалОзОÑПваММÑй кПÑÑÑОÑОеМÑ
setCompressionRatio();
//System.out.println("===============================================================");
return compressed;
}
private void setCompressionRatio() {//пПÑÑОÑаÑÑ ÐžÐŽÐµÐ°Ð»ÐžÐ·ÐžÑПваММÑй кПÑÑÑОÑОеМÑ
double sumA = 0, sumB = 0;//A-the original sum
for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
if (freqArray[i] != 0) {
sumA += 8 * freqArray[i];
sumB += encodingArray[i].length() * freqArray[i];
}
}
ratio = sumA / sumB;
}
public byte[] getBytedMsg() {//final compression
StringBuilder compressedString = new StringBuilder(getCompressedString());
byte[] compressedBytes = new byte[compressedString.length() / 8];
for (int i = 0; i < compressedBytes.length; i++) {
compressedBytes[i] = (byte) Integer.parseInt(compressedString.substring(i * 8, (i + 1) * 8), 2);
}
return compressedBytes;
}
//---------------------------------------end of compression----------------------------------------------------------------
//------------------------------------------------------------extract-----------------------------------------------------
public String extract(String compressed, String[] newEncodingArray) {
String decompressed = "";
String current = "";
String delta = "";
encodingArray = newEncodingArray;
//displayEncodingArray();
//пПлÑÑОÑÑ ÐºÐŸÐ»-вП вÑÑавлеММÑÑ
МÑлей
for (int i = 0; i < 8; i++)
delta += compressed.charAt(i);
int ADDED_ZEROES = Integer.parseInt(delta, 2);
for (int i = 8, l = compressed.length() - ADDED_ZEROES; i < l; i++) {
//i = 8, Ñ.к. пеÑвÑÐŒ байÑПЌ Ñ ÐœÐ°Ñ ÐžÐŽÐµÑ ÐºÐŸÐ»-вП вÑÑавлеММÑÑ
МÑлей
current += compressed.charAt(i);
for (int j = 0; j < ENCODING_TABLE_SIZE; j++) {
if (current.equals(encodingArray[j])) {//еÑлО ÑПвпалП
decompressed += (char)j;//ÑП ЎПбавлÑеЌ ÑлеЌеМÑ
current = "";//О ПбМÑлÑеЌ ÑекÑÑÑÑ ÑÑÑПкÑ
}
}
}
return decompressed;
}
public String getEncodingTable() {
String enc = "";
for (int i = 0; i < encodingArray.length; i++) {
if (freqArray[i] != 0)
enc += (char)i + encodingArray[i] + 'n';
}
return enc;
}
public double getCompressionRatio() {
return ratio;
}
public void displayEncodingArray() {//ÐŽÐ»Ñ ÐŸÑлаЎкО
System.out.println("======================Encoding table====================");
for (int i = 0; i < ENCODING_TABLE_SIZE; i++) {
//if (freqArray[i] != 0) {
System.out.print((char)i + " ");
System.out.println(encodingArray[i]);
//}
}
System.out.println("========================================================");
}
}
áááá¡á, á ááááá᪠á®ááá¡ á£á¬á§ááá¡ á€áááášá á©áá¬áá áá¡:
import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Closeable;
public class FileOutputHelper implements Closeable {
private File outputFile;
private FileOutputStream fileOutputStream;
public FileOutputHelper(File file) throws FileNotFoundException {
outputFile = file;
fileOutputStream = new FileOutputStream(outputFile);
}
public void writeByte(byte msg) throws IOException {
fileOutputStream.write(msg);
}
public void writeBytes(byte[] msg) throws IOException {
fileOutputStream.write(msg);
}
public void writeString(String msg) {
try (PrintWriter pw = new PrintWriter(outputFile)) {
pw.write(msg);
} catch (FileNotFoundException e) {
System.out.println("ÐевеÑМÑй пÑÑÑ, ОлО ÑакПгП Ñайла Ме ÑÑÑеÑÑвÑеÑ!");
}
}
@Override
public void close() throws IOException {
fileOutputStream.close();
}
public void finalize() throws IOException {
close();
}
}
áááá¡á, á ááááá᪠ááááááááá¡ á€ááááááá áááá®ááá¡:
import java.io.FileInputStream;
import java.io.EOFException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
public class FileInputHelper implements Closeable {
private FileInputStream fileInputStream;
private BufferedReader fileBufferedReader;
public FileInputHelper(File file) throws IOException {
fileInputStream = new FileInputStream(file);
fileBufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
}
public byte readByte() throws IOException {
int cur = fileInputStream.read();
if (cur == -1)//еÑлО закПМÑОлÑÑ Ñайл
throw new EOFException();
return (byte)cur;
}
public String readLine() throws IOException {
return fileBufferedReader.readLine();
}
@Override
public void close() throws IOException{
fileInputStream.close();
}
}
áá¡á, áá áááááá á áááá¡á:
import java.io.File;
import java.nio.charset.MalformedInputException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.util.List;
import java.io.EOFException;
public class Main {
private static final byte ENCODING_TABLE_SIZE = 127;
public static void main(String[] args) throws IOException {
try {//ÑказÑваеЌ ОМÑÑÑÑкÑÐžÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð°ÑгÑЌеМÑПв кПЌаМЎМПй ÑÑÑПкО
if (args[0].equals("--compress") || args[0].equals("-c"))
compress(args[1]);
else if ((args[0].equals("--extract") || args[0].equals("-x"))
&& (args[2].equals("--table") || args[2].equals("-t"))) {
extract(args[1], args[3]);
}
else
throw new IllegalArgumentException();
} catch (ArrayIndexOutOfBoundsException | IllegalArgumentException e) {
System.out.println("ÐевеÑМÑй ÑПÑÐŒÐ°Ñ Ð²Ð²ÐŸÐŽÐ° аÑгÑЌеМÑПв ");
System.out.println("ЧОÑайÑе Readme.txt");
e.printStackTrace();
}
}
public static void compress(String stringPath) throws IOException {
List<String> stringList;
File inputFile = new File(stringPath);
String s = "";
File compressedFile, table;
try {
stringList = Files.readAllLines(Paths.get(inputFile.getAbsolutePath()));
} catch (NoSuchFileException e) {
System.out.println("ÐевеÑМÑй пÑÑÑ, ОлО ÑакПгП Ñайла Ме ÑÑÑеÑÑвÑеÑ!");
return;
} catch (MalformedInputException e) {
System.out.println("ТекÑÑÐ°Ñ ÐºÐŸÐŽÐžÑПвка Ñайла Ме пПЎЎеÑжОваеÑÑÑ");
return;
}
for (String item : stringList) {
s += item;
s += 'n';
}
HuffmanOperator operator = new HuffmanOperator(new HuffmanTree(s));
compressedFile = new File(inputFile.getAbsolutePath() + ".cpr");
compressedFile.createNewFile();
try (FileOutputHelper fo = new FileOutputHelper(compressedFile)) {
fo.writeBytes(operator.getBytedMsg());
}
//create file with encoding table:
table = new File(inputFile.getAbsolutePath() + ".table.txt");
table.createNewFile();
try (FileOutputHelper fo = new FileOutputHelper(table)) {
fo.writeString(operator.getEncodingTable());
}
System.out.println("ÐÑÑÑ Ðº ÑжаÑÐŸÐŒÑ ÑайлÑ: " + compressedFile.getAbsolutePath());
System.out.println("ÐÑÑÑ Ðº кПЎОÑПвПÑМПй ÑаблОÑе " + table.getAbsolutePath());
System.out.println("Ðез ÑаблОÑÑ Ñайл бÑÐŽÐµÑ ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ОзвлеÑÑ!");
double idealRatio = Math.round(operator.getCompressionRatio() * 100) / (double) 100;//ОЎеалОзОÑПваММÑй кПÑÑÑОÑОеМÑ
double realRatio = Math.round((double) inputFile.length()
/ ((double) compressedFile.length() + (double) table.length()) * 100) / (double)100;//МаÑÑПÑÑОй кПÑÑÑОÑОеМÑ
System.out.println("ÐЎеалОзОÑПваММÑй кПÑÑÑОÑÐžÐµÐœÑ ÑжаÑÐžÑ ÑавеМ " + idealRatio);
System.out.println("ÐПÑÑÑОÑÐžÐµÐœÑ ÑжаÑÐžÑ Ñ ÑÑеÑПЌ кПЎОÑПвПÑМПй ÑаблОÑÑ " + realRatio);
}
public static void extract(String filePath, String tablePath) throws FileNotFoundException, IOException {
HuffmanOperator operator = new HuffmanOperator();
File compressedFile = new File(filePath),
tableFile = new File(tablePath),
extractedFile = new File(filePath + ".xtr");
String compressed = "";
String[] encodingArray = new String[ENCODING_TABLE_SIZE];
//read compressed file
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!check here:
try (FileInputHelper fi = new FileInputHelper(compressedFile)) {
byte b;
while (true) {
b = fi.readByte();//method returns EOFException
compressed += String.format("%8s", Integer.toBinaryString(b & 0xff)).replace(" ", "0");
}
} catch (EOFException e) {
}
//--------------------
//read encoding table:
try (FileInputHelper fi = new FileInputHelper(tableFile)) {
fi.readLine();//skip first empty string
encodingArray[(byte)'n'] = fi.readLine();//read code for 'n'
while (true) {
String s = fi.readLine();
if (s == null)
throw new EOFException();
encodingArray[(byte)s.charAt(0)] = s.substring(1, s.length());
}
} catch (EOFException ignore) {}
extractedFile.createNewFile();
//extract:
try (FileOutputHelper fo = new FileOutputHelper(extractedFile)) {
fo.writeString(operator.extract(compressed, encodingArray));
}
System.out.println("ÐÑÑÑ Ðº ÑаÑÐ¿Ð°ÐºÐŸÐ²Ð°ÐœÐœÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ " + extractedFile.getAbsolutePath());
}
}
áá¥ááá ááááá ááááá¬ááá á€ááááá¡ ááá¬áá á readme.txt ááá¡á¢á á£á¥áªááááá ð
ááá¡áááá
ááááá á¡á£á áá¡ áá§á á áá¡á áá¥áá᪠ááááááá. áᣠá áááá ááá¥áá á¡ááá¥áááá ááááá¡, ááááá ááááá¡, ááááááá, á áááá ááá¢ááááááªááá¡ ááá£áá¯áááá¡áááá¡ á©ááá¡ áá ááááááá¢ááá¢á£á ááááá, ááášáá ááááá¡á£á€ááá ááá¬áá áá. áᣠá ááá áá ááá®á¡ááá ááá¬áá á. á¡áááááááááá ááááá¡ááááá áá¥áááááá áááááá¢áá ááášá!
PS
áááá®, áááá®, áá áá¡áá áᥠááá , á ááááá áááá€ááªáááá¢á áá ááááááá¬á§áá. á¡á¢á áá¥áááá¡áááá¡ s1, ááááá áááá¡ áªá®á ááá áá¬áááá¡ 48 áááá¢á¡ - áááá áá ááŠáááá¢ááá áááááááá ááá á€áááá¡ áá áá áááááá¬á§áá¡ ááááá¢ááááá áá£áááá (ááááá¢ááá£áá áá£ááááá¡ á áááááááá áá áá¡ 7) => ášááá£áášááá¡ áááá€ááªáááá¢á áá¥áááá áá ááá ááááááá: 176 /(65 + 48*8 + 7) = 0.38. áᣠáá¥ááá᪠ášáááá©áááá áá¡, ááášáá á£áá áááá á¡áá®ááá áá á®áá á ááá¡á á£áááá£áá. áááá®, áá¡ áááá®áá áªáááááá á£áááá£á áá¡áá áá ááá€áá¥á¢á£á á áá¥áááá ááªáá á ááááá¡ á€ááááááá¡áááá¡. áááá áá á á á®áááá ááá á€áááááááá? á€ááááá¡ áááá áááá áá ááŠáááá¢ááá ááááá áááá¡ áªá®á áááá¡ ááááá¡. áá¡ áá áá¡ á¡ááá᪠ááááá áááá áá£ášáááá¡ áá¡á, á áááá ᪠á£ááá! ááááááááá, áááá¡áááá¡ áá á¥áááá¢áá á áá«áááá á áááá£á (áá á áááááááááá£á) áááá€ááªáááá¢á¡, á ááááá᪠á£áá áá¡ 1.46-á¡ - áááá¥ááá¡ áá áááá®áááá á¯áá ! áááá®, á€áááá áááááá¡á£á ááááá á£ááá á§áá€áááá§á.
á¬á§áá á: www.habr.com
