Created
February 13, 2020 10:44
-
-
Save lynzrand/f3c42cadfb64e76ff6f8d9684275cfaa to your computer and use it in GitHub Desktop.
Huffman encoding (old OJ question)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
int charrate[128] = {0}; | |
typedef struct _HuffmanNode { | |
int w, p, lc, rc; | |
} hfn; | |
typedef struct _HuffmanCode { | |
int l; | |
unsigned long long v; | |
} hfc; | |
/* | |
* === Encoding Style: === | |
* l: 6 | |
* v: 0 1 0 0 0 1 0 0 | |
* <---------> * * | |
*/ | |
hfn tree[256] = {{0}}; | |
int treetop = 128; | |
hfc code[128] = {{0}}; | |
const char _Input_File[] = "input.txt"; | |
const char _Output_File[] = "output.txt"; | |
int isAvailable(hfn* x) { return x->w > 0 && x->p < 128; } | |
int scanAndAddToTree() { | |
hfn* toadd = tree + treetop; | |
int mini = -1, minj = -1; | |
int i; | |
for (i = 0; i < treetop; i++) { | |
if (i == '\n' || !isAvailable(tree + i)) continue; | |
if (mini == -1 || (tree + i)->w < (tree + mini)->w) { | |
minj = mini; | |
mini = i; | |
} else if (minj == -1 || (tree + i)->w < (tree + minj)->w) { | |
minj = i; | |
} | |
} | |
if (minj == -1) return 0; | |
(tree + mini)->p = treetop; | |
(tree + minj)->p = treetop; | |
toadd->lc = mini; | |
toadd->rc = minj; | |
toadd->w = (tree + mini)->w + (tree + minj)->w; | |
treetop++; | |
return 1; | |
} | |
hfc travto(char c) { | |
int coef = 1; | |
int ptr; | |
hfc ret = {0}; | |
ptr = c; | |
while (tree[ptr].p != 0) { | |
if (tree[tree[ptr].p].rc == ptr) ret.v += coef; | |
coef <<= 1; | |
ptr = tree[ptr].p; | |
(ret.l)++; | |
} | |
ret.v <<= 8 * sizeof(long long) - ret.l; | |
return ret; | |
} | |
void dumphft() { | |
int i; | |
for (i = 0; i < 256; i++) { | |
printf("%5d %5d %5d %5d %5d \n", i, tree[i].w, tree[i].p, tree[i].lc, | |
tree[i].rc); | |
} | |
} | |
void dumphfc() { | |
int i; | |
for (i = 0; i < 128; i++) { | |
printf("%5d %016llx %5d\n", i, code[i].v, code[i].l); | |
} | |
} | |
int main() { | |
FILE *input, *output; | |
input = fopen(_Input_File, "r"); | |
{ | |
// ==== Read In ==== | |
char c; | |
while ((c = fgetc(input)) != EOF) { | |
(tree[c].w)++; | |
} | |
tree['\0'].w = 1; | |
// ==== Create Huffman Tree ==== | |
while (scanAndAddToTree()) | |
; // empty loop! | |
} | |
fseek(input, 0, 0); | |
// dumphft(); | |
// ==== Create Huffman Code ==== | |
{ | |
int i; | |
for (i = 0; i < 128; i++) { | |
code[i] = travto(i); | |
} | |
// code[17].v = 0x2200; | |
} | |
// dumphfc(); | |
// ==== Output ==== | |
{ | |
unsigned long long buf = 0; | |
int offset = 0; | |
const int endOffset = 8 * sizeof(long long) - 8; | |
char c; | |
output = fopen(_Output_File, "w"); | |
while ((c = fgetc(input)) != EOF) { | |
if (c == '\n') { | |
fputc(c, output); | |
continue; | |
} | |
buf |= (code[c].v >> offset); | |
offset += code[c].l; | |
// & (-1 << (sizeof(long long) - offset)); | |
if (offset >= 8) | |
while (offset >= 8) { | |
unsigned char buf2; | |
buf2 = buf >> endOffset; | |
buf = buf << 8; | |
offset -= 8; | |
printf("%hhx", buf2); | |
fputc(buf2, output); | |
} | |
// printf(" %llx %5d\n", buf, offset); | |
} | |
buf |= (code[0].v >> offset); | |
offset += code[0].l; | |
while (offset > 0) { | |
unsigned char buf2; | |
buf2 = buf >> endOffset; | |
buf = buf << 8; | |
offset -= 8; | |
printf("%hhx", buf2); | |
fputc(buf2, output); | |
} | |
} | |
fclose(input); | |
fclose(output); | |
putchar('\n'); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment