entry ááá¯
á€áá±á¬ááºážáá«ážááœááºá áá¬áááºááŒá®áž Huffman algorithm ááŸáá·áº data compression á¡ááœááºáááºážáá¡áá¯á¶ážáá»áááá¯ááááºá¡ááŒá±á¬ááºážááŒá±á¬áá«áááºá
ááááºá¡áá±áá²á· ááá¯ážááá¯ážááŸááºážááŸááºáž archiver ááá¯áá±ážáá«áááºá áá®ááá¯ááŒá
áºáá±ááŒá®á
á¡áááºážáááºáá±á¬ááºááŒááºáááº
áá¯á¶ááŸááºá á¬áá¬ážááá¯ááºááœááºá á á¬áá¯á¶ážáá áºáá¯á¶ážááᯠ8 bits (ASCII áá¯ááºáá¶áá«ááº) ááá¯á·ááá¯áẠ16 (Unicode áá¯ááºáá¶áá«ááº) ááŒáá·áº áá¯ááºáá¯ááºáá¬ážáááºá áá±á¬ááºáá áºáá¯á áá»áœááºá¯ááºááá¯á·ááẠASCII áá¯ááºáá¶áá«ááºááᯠáá¯á¶ážáááºáá«áááºá á¥ááá¬á string s1 = "SUSIE SAYS IS IS EASYn" ááᯠáá°áá«á á á¯á á¯áá±á«ááºážá áá»ááºážááŒá±á¬ááºážááœáẠá á¬áá¯á¶áž 22 áá¯á¶ážáá«ááŸáááŒá®ážá áá±áá¬ááœááºáá»á¬ážááŸáá·áº ááá¯ááºážá¡áá áºá¡áá¹ááᬠ- 'n' ááá¯á· áá«áááºáááºá á€á á¬ááŒá±á¬ááºážáá«ááŸááá±á¬ááá¯ááºááẠ22*8 = 176 bits á¡áá±ážáá»áááºááŸááá«áááºá áá±ážááœááºážáá»ááºáá»ááºážáá±á«áºáá¬áááº- á á¬áá¯á¶áž 8 áá¯á¶ážááᯠáá¯ááºáá¯ááºááẠ1 bits á¡á¬ážáá¯á¶ážááᯠá¡áá¯á¶ážááŒá¯ááŒááºážááẠáá»áá¯ážááŒá±á¬ááºážáá®áá»á±á¬áºááŸá¯ááŸááá«ááá¬ážá áá»áœááºá¯ááºááá¯á·ááẠASCII á á¬áá¯á¶ážá¡á¬ážáá¯á¶ážááᯠááá¯á¶ážáá«á áááºážááá¯á·ááŒá áºáá»áŸááºáááºá á¡áá»á¬ážáá¯á¶ážá¡áá¹ááᬠ- S - ááŒá áºááá¯ááºááá»áŸá¡ááá¯áá¯á¶ážáá¯ááºááŸáá·áº á¡ááŸá¬ážáá«ážáá¯á¶ážá á¬áá¯á¶áž - T (ááá¯á·ááá¯áẠUá ááá¯á·ááá¯áẠ'n') - áá¯ááºááᯠááá¯áá á áºááŸááºá¡á±á¬áẠáá±ážááŒááºážááẠááá¯á áááºááŒááºáá¯á¶ááá¬ážááŒá áºáááá·áºáááºá áááºážááẠHuffman algorithm ááŒá áºáááº- ááá¯ááºááẠá¡áááºážáá¯á¶ážá¡áá±ážáá»áááºááŸáááá·áº á¡áá±á¬ááºážáá¯á¶ážáá¯ááºáá¶áá«ááºááœá±ážáá»ááºááŸá¯ááᯠáááºááŸá¬ááœá±áááºááá¯á¡ááºáááºá ááá°áá®áá±á¬ áá¬ááºáá±á¬ááºáá»á¬ážááẠáá¯ááºá¡ááŸááºáá»á¬áž ááŸááááºááŸá¬ áá¯á¶ááŸááºááŒá áºááẠ- áááºážááẠá¡ááºáááá¯áá®áááºá á¡ááŒá±áá¶ááŒá áºáááºá
ПЎОÑПваМОе
á¡áááºááŒá±á¬áá·áºááá¯áá±á¬áº á á¬áá¯á¶áž 'S' ááᯠáá¯ááºáá áºáᯠááá±ážáááŒááºáž á¥ááá¬á 1 bit á¡ááŸááº- 0 ááá¯á·ááá¯áẠ1á áááºážááᯠ1 ááŒá áºáá«á á±á ááá¯á·áá±á¬áẠáá¯áááá¡áá»á¬ážáá¯á¶áž áá¬ááºáá±á¬áẠ- ' ' (space) - 0 áá±ážáá«áááºá á áááºáá°ážááŒáá·áºáá«á ááá·áºá á¬ááá¯ááᯠáá¯ááºáá¯ááºáá¬ážáá±á¬ á á¬ááŒá±á¬ááºáž s1 ááᯠáá¯ááºáá»ááºáá« - áá¯ááºááẠ1 ááŒáá·áº á áááºáááºááᯠáááºááœá±á·ááŒááºááááºá áá®áá±á¬á· áá¬áá¯ááºáááá²á á¡á²áá«á á á¬áá¯á¶áž S áá¬ážá áá«ááŸááá¯áẠA ááá¯áá»áá¯áž áááŒá¬áž áá¬ááºáá±á¬ááºáá¬áž? ááá¯á·ááŒá±á¬áá·áº á¡áá±ážááŒá®ážáá±á¬ á ááºážáá»ááºážáá áºáᯠáá±á«áºáá¬ááẠá
áááºááá·áºáá¯ááºá០á¡ááŒá¬ážáá áºáá¯á ááŸá±á·áááºááŒá áºááá«áááºá
á€á ááºážáá»ááºážááẠalgorithm ááá±á¬á·áá»ááºááŒá áºáááºá ááá¯á·ááŒá±á¬áá·áºá áááºá¹áá±ááá áºáá¯á á®á ááŒáááºááŸá¯ááºáž (ááŒá áºáá»ááºááŸá¯á¡áá±á¡ááœááº) ááá¯ááœáŸááºááŒááá·áº ááŒáááºááŸá¯ááºážááá¬ážááŒáá·áº á¡á ááŒá¯á áá¯ááºááᯠáááºáá®ážááŒááºážááŒá áºáááºá
á¡áá»á¬ážáá¯á¶ážááŒá áºáá±á«áºááá·áº áá¬ááºáá±á¬ááºáá»á¬ážááᯠá¡áááºážáá¯á¶ážááŒáá·áº áá¯ááºáá¯ááºáá¬ážááá·áºáááºá ááŒá áºááá¯ááºááẠbits á¡áá±á¡ááœááºá ááŒá áºááá¯ááºáá»á±ááŸááá±á¬ áá¯ááºááá¬ážáá»á¬ážáá²á០áá áºáá¯ááᯠá¥ááá¬áá áºáá¯áá±ážáá«áááºá
ááá¯á·ááŒá±á¬áá·áº áá¯ááºáá¯ááºáá¬ážáá±á¬ áááºáá±á·áá»áºááẠá€áá²á·ááá¯á· ááŒá áºáá±áááá·áºáááº-
10 01111 10 110 1111 00 10 010 1110 10 00 110 0110 00 110 10 00 1111 010 10 1110 01110
á
á¬áá¯á¶ážáá
áºáá¯á¶ážáá»ááºážá
á®áá²á· áá¯ááºááœá±ááᯠáá±áá¬ááœááºáá
áºáá¯áá²á· ááœá²ááá¯ááºáááºá áá»á¯á¶á·áá¬ážáá±á¬ááá¯ááºááœáẠáááºážááẠá¡ááŸááºááááºááŒá
áºáááºááá¯ááºáá«á
áá±ážááœááºážáá±á«áºáá¬áááº- á€áá°áá
áºááẠáá¯ááºááá¬ážáá
áºáá¯ááᯠáááºááá¯á·áááºáá®ážááááºáááºážá áá«ááᯠá¡á±á¬ááºááŸá¬ ááœá±ážááœá±ážáá«áááºá
Huffman áá áºáááºáááºáá±á¬ááºááŒááºážá
á€áá±áá¬ááœáẠááœáá á¯á¶ááŸá¬ááœá±áá±ážáá áºáááºáá»á¬ážá áááºáááºáá¬áá±áá¬ááŒá áºáááºá á áááºááá°áá«ááŸáá·áºá á€áá±áá¬ááœáẠááŸá¬ááœá±ááŒááºážá ááá·áºááœááºážááŒááºážááŸáá·áº áá»ááºááŒááºážáááºážáááºážáá»á¬ážááᯠáááá¯á¡ááºáá«á á€áááºááŸá¬ java ááŸá áá áºáááºááœá²á·á ááºážáá¯á¶ááŒá áºááẠá
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;
}
...
}
áááºážááẠáá¯ááºá¡ááŒáá·áºá¡á á¯á¶ááá¯ááºáá«á áá¯ááºá¡ááŒáá·áºá¡á á¯á¶ááŸá¬ á¡á±á¬ááºáá«á¡ááá¯ááºáž ááŒá áºáá«áááá·áºáááºá
á€áááºááŸá¬ áá áºáááºáá áºáááºáááºáá±á¬ááºááŒááºážá¡ááœáẠalgorithm ááŒá áºááẠá
- áááºáá±á·áá»áº (ááá¯ááºáž s1) á០áá¬ááºáá±á¬ááºáá áºáá¯á á®á¡ááœáẠNode á¡áá¬ááá¹áá¯áá áºáá¯ááᯠáááºáá®ážáá«á áá»áœááºá¯ááºááá¯á·áá¡ááŒá±á¡áá±ááœááºá Node 9 áᯠ(Node objects) ááŸááááá·áºáááºá node áá áºáá¯á á®ááœáẠáá±áá¬áááºáááºááŸá áºáá¯áá«ááŸááááº- áááºá¹áá±áááŸáá·áº ááŒáááºááŸá¯ááºáž
- Node node áá áºáá¯á á®á¡ááœáẠTree object (BinaryTree) ááá¯áááºáá®ážáá«á node ááẠáá áºáááºá á¡ááŒá áºááŒá áºáá¬áááºá
- á€áá áºáááºáá»á¬ážááᯠáŠážá á¬ážáá±ážáááºážá á®ááœáẠááá·áºááœááºážáá«á ááŒáááºááŸá¯ááºážáááá·áºáá±á áŠážá á¬ážáá±ážááŸá¯ ááá¯áá»á¬ážáá±ááŒá áºáááºá ááá¯á·ááŒá±á¬áá·áº áá¯ááºáá°ááá·áºá¡áá«ááœáẠá¡áááá·áºáá¯á¶ážá¡ááŒáááºááŸá¯ááºážááŸáááá·áº áá áºáááºááᯠá¡ááŒá²áááºážááœá±ážáá»ááºáááºá
ááá¯á·áá±á¬ááºá áááºááẠá¡á±á¬ááºáá«ááá¯á·ááᯠá ááºáá®ážá á®ážááẠááá¯á¡ááºáááºá
- áŠážá á¬ážáá±ážáááºážá á®á០áá áºáááºááŸá áºáááºááᯠáá¯ááºáá°ááŒá®áž áááºážááá¯á·ááᯠnode á¡áá áºáá áºáᯠ(á¡áá¹ááá¬áá áºáá¯ááá«áá² á¡áá áºáááºáá®ážáá¬ážáá±á¬ áá¯ááºáá áºáá¯) ááᯠááá±ážáá»á¬ážá¡ááŒá ẠááŒá¯áá¯ááºáá«á node á¡áá áºá ááŒáááºááŸá¯ááºážááẠáá»áá¯ážáááºáá áºáá áºáááºááŸá áºáá¯á ááŒáááºááŸá¯ááºážáá±á«ááºážáááºááŸáá·áº áá®áá»áŸáááºá
- ဠnode á¡ááœááºá ဠnode ááœáẠá¡ááŒá áºááœááºáá±áá±á¬ áá áºáááºááᯠáááºáá®ážáá«á á€áá áºáááºááᯠáŠážá á¬ážáá±ážáááºážá á®áá²ááá¯á· ááŒááºááá·áºáá«á (áá áºáááºááœáẠááŒáááºááŸá¯ááºážá¡áá áºááŸááá±á¬ááŒá±á¬áá·áºá áááºážááẠáááºážá á®ááá·áºáá±áá¬á¡áá áºááá¯á· áá±á¬ááºááŸáááá¯ááºááŒá±áá»á¬ážáá«áááºá)
- áááºážá á®áá¬ááœáẠáá áºáááºáá áºáááºáá»ááºáááºá¡áá - Huffman áá áºááẠá¡ááá·áº 1 ááŸáá·áº 2 ááá¯áááºáá¯ááºáá«á
ááá¯ááºáž s1 ááœáẠဠalgorithm ááᯠáá¯á¶ážáááºáá« á
á€áá±áá¬ááœáẠáááºá¹áá±á "lf" (linefeed) ááẠá
á¬ááŒá±á¬ááºážá¡áá
áºááᯠáááºááœáŸááºážáááºá "sp" (space) ááẠspace áá
áºáá¯ááŒá
áºáááºá
áá±á¬ááºáá áºáá¯ááá¬áá²?
áá»áœááºáá±á¬áºááá¯á· Huffman áá áºáááºááᯠááá²á·áá«áááºá á¡áá¯áá±áááºáá±á¬áºá á¡á²áá«áá²á· áá¬áá¯ááºáááá²á á¡á²áá«ááᯠá¡ááá¬ážááá°ááŒáá°ážáááŒá®ážáá±á¬á· á¡ááŒá áºááá± áá áºáááºáá²á· á¡ááœááºááœá±á¡áá ááŒá áºááá¯ááºáá²á·áááºážááŒá±á¬ááºážá¡á¬ážáá¯á¶ážááᯠááŒá±áá¬áá¶ááá¯á· ááá¯áá«áááºá áááºáááºááá¯á· áŠážáááºááœá¬ážáá«á á¡á áœááºážáá áºáá¯ááᯠ0 áá¶ááááºáááºáááºááŸáá·áº áá¬áááºááá¯á· áŠážáááºááœá¬ážáá«á 1 ááᯠááá±á¬áá°áá«áááºá á¡ááá¡áá»ááŒá±á¬ááá»áŸáẠá€ááŸááºá á¯áá»á¬ážááœáẠá¡áá¹ááá¬áá¯ááºááẠáá áºáááºáá¡ááŒá áºá០á€á á¬áá¯á¶ážáá«ááŸááá±á¬ á¡ááœááºáá®ááá¯á· áááºážááŒá±á¬ááºážááŒá áºáááºá
ááá¯á·ááŒá±á¬áá·áº áá¯ááºááá¬áž áá±á«áºáá¬áááºá á€ááá¬ážááᯠáá¯á¶ážáááºáá«áá á¡áá¹ááá¬áá
áºáá¯á
á®á "á¡áá±ážáá»áááº" á¡ááŒá±á¬ááºáž áá±á¬ááºáá»ááºáá»ááá¯ááºááẠ- áááºážááẠáááºážááá¯ááºáá¡ááŸááºááŒá
áºáááºá ááá¯á·áá±á¬áẠááááááºáá¬ážáá±á¬áá¯á¶á
á¶ááŒáá·áº á¡áááºážá¡ááŒá
áºááá¯ááºááẠá¡áá±ážáá»áááº- 2*3+2*4+3*3+6*2+1*4+1*5+2*4+4*2+1*5 = 65 bits . ááááá±á¬á· 176 bits á¡áá±ážáá»áááºááŸááááºá ááá¯á·ááŒá±á¬áá·áºá áá»áœááºá¯ááºááá¯á·ááẠáááºážááᯠ176/65 = 2.7 á áá»áŸá±á¬á·áá»áá²á·áááºá áá«áá±ááá·áº áá«á Utopia áá«á ááá¯ááá¯á·áá±á¬á¡áá»áá¯ážá¡á
á¬ážááᯠáááŸáááẠáááŒá
áºááá¯ááºáá±á á¡áááºááŒá±á¬ááºá·? áá«ááᯠáááºážáááºážááŒá¬á០ááœá±ážááœá±ážáá«áááºá
áá¯ááºááœá²ááŒááºážá
áá±á¬ááºážááŒá®á áá»ááºáá¬á á¡ááá¯ážááŸááºážáá¯á¶ážá¡áá¬á decoding ááŒá áºááá¯ááºáá«áááºá áá¯ááºááœááºážáááºážááᯠá¡ááááºá¡ááŒáœááºááá«áá² áá»á¯á¶á·áá¬ážáá²á·ááá¯ááºááᯠááá¯ážááá¯ážááŸááºážááŸááºáž áááºáá®ážááá¯á·ááá¯áᬠáááŒá áºááá¯ááºáá°ážááá¯á· áá±á¬áºáá±á¬áºáá»á¬ážáá»á¬ážá ááŸááºážááá¬ážááŒáááºáááºáá«ááẠ- á¡á²áá«ááᯠáá¯ááºáá¯ááºááá¯á· áááá«áá°ážá áá¯ááºáá²á·á áá¯ááºáá²á·á áá«ááᯠáá¬ážáááºááá¯á· áááºáá«áááºá áá«áá±ááá·áº compression table áá²á· text file áá áºáᯠtable.txt ááᯠáááºáá®ážááá«áááºá
01110
00
A010
E1111
I110
S10
T0110
U01111
Y1110
'áá¬ááºáá±á¬ááº' "áá¬ááºáá±á¬ááºáá¯ááº" áá±á¬ááºááœáẠááá¬ážááá·áºááœááºážááŒááºážá 01110 ááẠá¡áááºááŒá±á¬áá·áº áááºá¹áá±ááááŸáááááºážá á¡ááŸááºááŸá¬á áááºážááẠáááºá¹áá±ááá áºáá¯ááŒáá·áº ááŒá áºáááºá ááá¯ááºáá áºáá¯ááá¯á· áá¯ááºáá±ážááá·áºá¡áá« áá»áœááºá¯ááºá¡áá¯á¶ážááŒá¯ááá·áº java áááááá¬áá»á¬ážáá¬ááŒá áºááŒá®ážá ááá¯ááºážá¡áá áºá¡áá¹ááᬠ- 'n' - ááẠá¡áá áºááá¯ááºážá¡ááŒá áºááá¯á· ááŒá±á¬ááºážáá²ááœá¬ážááẠ(áááºáá»áŸááẠááá¯ááºáá²áá±áá«á á±)á ááá¯á·ááŒá±á¬áá·áº á¡áááºáá±á¬áºááŒáá« á¡ááœááºá á¬ááŒá±á¬ááºážááẠáá¯áẠ01110 á¡ááœáẠá á¬áá¯á¶ážááŒá áºáááºá áá¯áẠ00 á¡ááœááºá á á¬áá¯á¶ážááẠá á¬ááŒá±á¬ááºážáá¡á ááœáẠáá±áá¬ááœááºáá áºáá¯ááŒá áºáááºá áá®ááá¬ážááᯠááááºážáááºážáá²á·áááºážáááºážá áá»áœááºá¯ááºááá¯á·áá²á· Khan coefficient á¡ááœáẠá¡áá¯á¶ážááá»áá¯á¶ážááá¯á· áá»ááºáá»ááºážááŒá±á¬ááá«áááºá áá«áá±ááá·áº áá¬ážáááºááŒá®áž á¡áá±á¬ááºá¡áááºáá±á¬áºááá¯á· ááœááºáá«áááºá ááá¯ááá¯áá±á¬ááºážááœááºá¡á±á¬ááºááŒá¯áá¯ááºááŒááºážááá¯ááºáᬠááŸááºáá»ááºáá»á¬ážááœáẠáááºáá¡ááŒá¶ááŒá¯áá»ááºáá»á¬ážááᯠááŒá¬ážáá¬áááá·áºá¡ááœáẠáááºážáá¬áá«áááºá
á€ááá¬ážááŒáá·áºá áááºážááẠáá¯ááºáá»ááºááẠá¡ááœááºááœááºáá°áááºá áá¯ááºáá¶áá«ááºááᯠáááºáá®ážáá±á¬á¡áá« áá»áœááºá¯ááºááá¯á·ááẠáááºááá·áºá ááºážáá»ááºážááᯠáááºážááœáŸááºáá¬ážáááºááᯠááááááŒáá«á áá¯á·á
áááºááá·áºáá¯ááºá០á¡ááŒá¬ážáá áºáá¯á ááŸá±á·áááºááŒá áºááá«áááºá
áá«á á¡áááºááŒá±áá»á±á¬ááœá±á·áá²á· á¡áááºážááá¹áááŸá¬ áá«áááºáá«áááºá áá»áœááºá¯ááºááá¯á·ááẠáá áºáááºááŒá®ážáá áºá á á®á á¥áºáááºááŒááŒá®áž ááœááºáá±á«áºáá¬áá±á¬ á á¬ááŒá±á¬ááºáž d á áááºáá áºáá»á¬ážáá«ááŸááá±á¬á áá¬ááºáá±á¬ááºáá¬ááºáá±á¬ááºááŸáá·áº áááºááá¯ááºááá·áº áá¯ááºáá¶áá«ááºááᯠááá¯ááºáá®áááºááŸáá·áºá¡áá»áŸ áá¬ááºáá±á¬ááºáá¬ááºáá±á¬áẠ(ááŸáá·áº áá áºáá¯áááºážáá±á¬ á¡áá¹ááá¬!) ááᯠáá¯ááºáá¯ááºáá¬ážáááºááᯠáá»áœááºá¯ááºááá¯á· áá»ááºáá»ááºážáááá«áááºá ááá¯á·áá±á¬ááºá áá»áœááºá¯ááºááá¯á·ááẠáá¯ááºá á¬ááŒá±á¬ááºážááá¯á· á á¬áá¯á¶ážááá¯áá±ážááŒá®áž (áá¯ááºáá¯ááºáá¬ážáá±á¬ á á¬ááŒá±á¬ááºážáá«ááŸááá±á¬ á á¬ááŒá±á¬ááºáž)á d string ááᯠáá¯ááᯠáááºááŸááºááŒá®áž áá¯ááºáá¯ááºáá¬ážáá±á¬ ááá¯ááºááᯠáááºáááºáá«á
á¡áá±á¬ááºá¡áááºáá±á¬áºááŸá¯
archiver áá±ážááŒááºážááŒáá·áº áá»áœááºá¯ááºááá¯ááºááᯠá¡ááŸááºáááẠá¡áá»áááºáááºááŒá®á á¡á²áá«ááᯠCompressor ááá¯á· áá±á«áºáá¡á±á¬ááºá
ááŒááºá áá«á ááááá¯á¶ážá¡áá±áá²á· Node class ááᯠáá±ážáá«áááºá
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;//вПзвÑаÑаеЌ ÑЎалеММÑй ÑлеЌеМÑ(ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÐœÐ°ÐžÐŒÐµÐœÑÑей ÑаÑÑПÑПй)
}
}
Huffman áá áºáááºááᯠáááºáá®ážááá·áº á¡áááºážá
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
áá¯ááºáááºá áá¯ááºáááºá áá«áá®ááŸá¬ááŸááá±áá¯ááºážáá²á áá¬ááŒá
áºááá¯á·áá²ááá¯áá±á¬á· coefficient ááá¯áá«ááá±á·áá²á·áá°ážá string s1 á¡ááœááºá encoding table ááẠ48 bytes á¡áá±ážáá»áááºááŸáááŒá®áž áá°áááºážááá¯ááºááẠáá»á¬ážá
áœá¬ááá¯á á¡ááá¯áá¯á (áá±á«ááºážááá·áºáá¬ážáá±á¬ áá¯áá¡áá±á¡ááœááºááŸá¬ 7) => compression ratio ááẠáá
áºáá¯áááºáááºážáá«áááº- 176 /(65+48*8+7) = 0.38á áá«ááá¯áááºáž áááááŒá¯ááááẠááŒá®ážááœá¬ážáá¯á¶áá²á· áááŒá®ážáá«áá°ážá áá¯ááºáá«áááºá á€á¡áá±á¬ááºá¡áááºáá±á¬áºááŸá¯ááẠáá±ážáááºáá±á¬ááá¯ááºáá»á¬ážá¡ááœáẠá¡ááœááºáááá±á¬ááºááŸá¯áááŸááá«á áá«áá±ááá·áº ááá¯ááºááŒá®ážááœá±á áá¬ááŒá
áºááá²á ááá¯ááºá¡ááœááºá¡á
á¬ážáá»á¬ážááẠáá¯ááºáá¶áá«ááºááá¬ážá¡ááœááºá¡á
á¬ážááẠáá»á¬ážá
áœá¬ááŒá®ážáá¬ážáááºá á€áá±áá¬ááœáẠalgorithm ááẠáááºážáá²á·ááá¯á· á¡áá¯ááºáá¯ááºáá«áááºá á¥ááá¬á¡á¬ážááŒáá·áºá
source: www.habr.com