Merhaba,
Bu müthiş algoritmayı kodlamadan evvel hazır bir C kodunu uyarlayım dedim. Şurada (http://www.programminglogic.com/implementing-huffman-coding-in-c/) çok güzel bir makaleye (by Daniel Scocco) denk geldim. Gerçi Türkçesi de var (-bknz. Huffman Kodu – Veri sıkıştırmanın temelleri (<www.yaksari.com/2009/04/huffman-kodu-veri-sikistirmanin-temelleri/>) - Bilg. Müh. Yiğitcan Aksarı) ama makale sonundaki kodun bağlantı adesi (kırık) maalesef erişim dışı...:)
Neyse, dil sorun değil sonuçta ama İngilizce ve C olması yeterliydi ama yine de şu aşağıdaki kodda (Daniel'in kodu) bir kaç hata (başlangıçta sadece 3 tane ama sonra 2 tane daha çıkmalı!) almaktayım. Çözemediğim için yardım ederseniz sevinirim:
import std.stdio, std.math;
struct node {
int value;
char letter;
node *left, right;
}
alias node Node;
int[] englishLetterFrequencies = [ 81, 15, 28, 43, 128, 23, 20, 61, 71, 2, 1,
40, 24, 69, 76, 20, 1, 61, 64, 91, 28, 10, 24, 1, 20, 1, 130 ];
int findSmaller (ref Node* array[], int differentFrom){
int smaller;
int i = 0;
while(array[i].value == -1) i++;
smaller = i;
if(i == differentFrom)
{
i++;
while (array[i].value == -1) i++;
smaller = i;
}
for(i = 1; i < 27; i++)
{
if(array[i].value == -1) continue;
if(i == differentFrom) continue;
if(array[i].value < array[smaller].value) smaller = i;
}
return smaller;
}
void buildHuffmanTree(ref Node *tree){
Node *temp;
Node *array[27];
int i, subTrees = 27;
int smallOne, smallTwo;
for(i = 1; i < 27; i++)
{
array[i] = new Node();
array[i].value = englishLetterFrequencies[i];
array[i].letter= cast(char)i;
array[i].left = null;
array[i].right = null;
}
while (subTrees > 1)
{
smallOne = findSmaller(array, -1);
smallTwo = findSmaller(array, smallOne);
temp = array[smallOne];
array[smallOne] = new Node();
array[smallOne].value = temp.value + array[smallTwo].value;
array[smallOne].letter= 127;
array[smallOne].left = array[smallTwo];
array[smallOne].right = temp;
array[smallTwo].value = -1;
subTrees--;
}
tree = array[smallOne];
}
void fillTable(int[] codeTable, Node *tree, int Code){
if(tree.letter < 27)
{
codeTable[cast(int)tree.letter] = Code;
}
else
{
fillTable(codeTable, tree.left, Code * 10 + 1);
fillTable(codeTable, tree.right, Code * 10 + 2);
}
}
void compressFile(File input, File output, int[] codeTable){
char bit, c, x = 0;
int n, length, bitsLeft = 8;
int originalBits = 0, compressedBits = 0;
while((c=input.getc()) != 10){
originalBits++;
if(c == 32)
{
length = (cast(int)log10(codeTable[26])) + 1;
n = codeTable[26];
} else {
length = (cast(int)log10(codeTable[c - 97])) + 1;
n = codeTable[c - 97];
}
while(length > 0) {
compressedBits++;
bit = n % 10 - 1;
n /= 10;
x = x | bit;
bitsLeft--;
length--;
if (bitsLeft == 0)
{
output.write(x);
x = 0;
bitsLeft = 8;
}
x = x << 1;
}
}
if (bitsLeft != 8)
{
x = x << (bitsLeft - 1);
output.write(x);
}
writeln(stderr, "Original bits = ",originalBits * 8);
writeln(stderr, "Compressed bits = ", compressedBits);
writeln(stderr, "Saved percent of memory = ", (cast(float) compressedBits / (originalBits * 8)) * 100);
}
void decompressFile (File input, File output, Node *tree){
Node *current = tree;
char c, bit;
char mask = 1 << 7;
int i;
while(input.eof()){
c = input.getc();
for(i = 0; i < 8; i++) {
bit = c & mask;
c = c << 1;
if(bit == 0) {
current = current.left;
if(current.letter != 127) {
if(current.letter == 26) output.write(32);
else output.write(current.letter + 97);
current = tree;
}
}
else
{
current = current.right;
if(current.letter != 127) {
if(current.letter == 26) output.write(32);
else output.write(current.letter + 97);
current = tree;
}
}
}
}
}
void invertCodes(int[] codeTable, int[] codeTable2){
int i, n, copy;
for(i = 0; i < 27; i++)
{
n = codeTable[i];
copy = 0;
while(n > 0) {
copy = copy * 10 + n %10;
n /= 10;
}
codeTable2[i] = copy;
}
}
void main(){
Node *tree;
File input, output;
char[] filename = new char[20];
int[] codeTable = new int[27];
int[] codeTable2 = new int[27];
int compress;
buildHuffmanTree(&tree);
fillTable(codeTable, tree, 0);
invertCodes(codeTable, codeTable2);
writeln("Type the name of the file to process :"); scanf("%s", filename);
writeln("Type 1 to compress and 2 to decompress:"); scanf("%d", &compress);
input = File(filename, "r");
output = File("output.txt","w");
if(compress == 1) compressFile(input, output, codeTable2);
else decompressFile(input, output, tree);
}
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]