Skip to content

Instantly share code, notes, and snippets.

@lynzrand
Created February 13, 2020 10:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lynzrand/f3c42cadfb64e76ff6f8d9684275cfaa to your computer and use it in GitHub Desktop.
Save lynzrand/f3c42cadfb64e76ff6f8d9684275cfaa to your computer and use it in GitHub Desktop.
Huffman encoding (old OJ question)
#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