path-packer-c/huffman.c
2012-08-11 14:16:29 -03:00

100 lines
1.8 KiB
C

#include "huffman.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static int
find_smallest (struct huffman_node **nodes, int count, int different)
{
int smallest;
int i;
for (i = 0; nodes[i]->weight == -1; i++);
if (i == different) {
for (i++; nodes[i]->weight == -1; i++);
}
smallest = i;
for (i = smallest + 1; i < count; i++) {
if (i == different || nodes[i]->weight == -1) {
continue;
}
if (nodes[i]->weight < nodes[smallest]->weight) {
smallest = i;
}
}
return smallest;
}
struct huffman_node *
huffman_build_tree(void **values, int count)
{
int i;
struct huffman_node **nodes;
nodes = malloc (sizeof (struct huffman_node *) * count);
for (i = 0; i < count; i++) {
struct huffman_node *node =
malloc (sizeof (struct huffman_node));
node->value = values[i];
node->weight = i + 1;
node->left = NULL;
node->right = NULL;
nodes[i] = node;
}
int tree1;
int tree2;
for (i = 1; i < count; i++) {
struct huffman_node *tmp;
tree1 = find_smallest (nodes, count, -1);
tree2 = find_smallest (nodes, count, tree1);
tmp = nodes[tree1];
nodes[tree1] = malloc (sizeof (struct huffman_node));
nodes[tree1]->weight = tmp->weight + nodes[tree2]->weight;
nodes[tree1]->value = NULL;
nodes[tree1]->left = nodes[tree2];
nodes[tree1]->right = tmp;
nodes[tree2]->weight = -1;
}
return nodes[tree1];
}
void *
huffman_lookup (struct huffman_node *tree, unsigned char *bits, int *bits_read)
{
struct huffman_node *node = tree;
while (true) {
if (node == NULL) {
return NULL;
}
if (node->value != NULL) {
return node->value;
}
if ((bits[0] << *bits_read % 8 & 0x80) == 0) {
node = node->left;
} else {
node = node->right;
}
(*bits_read)++;
if (*bits_read % 8 == 0) {
bits++;
}
}
}