Update node ordering algorithm for huffman encoding
This commit is contained in:
parent
3d94813dc8
commit
790d494da1
3 changed files with 43 additions and 22 deletions
|
@ -79,5 +79,7 @@ different valid huffman trees, depending on the algorithm used. Thus it is
|
||||||
important to use an algorithm that will give the same ordering. See the code
|
important to use an algorithm that will give the same ordering. See the code
|
||||||
for more details, but in a nuttshell:
|
for more details, but in a nuttshell:
|
||||||
|
|
||||||
|
Order the list of nodes by weight (lightest to heaviest). Take the first two lightest nodes off the list, and set them as children of a new parent node. add this parent node to the end of the node list, after removing the child nodes from the list.
|
||||||
|
|
||||||
When comparing nodes, the node that weighs the least becomes the left child. If
|
When comparing nodes, the node that weighs the least becomes the left child. If
|
||||||
weight is tied, the node that was examined longest ago becomes the left child.
|
weight is tied, the node that was examined longest ago becomes the left child.
|
||||||
|
|
52
huffman.c
52
huffman.c
|
@ -7,22 +7,17 @@
|
||||||
static int
|
static int
|
||||||
find_smallest (struct huffman_node **nodes, int count, int different)
|
find_smallest (struct huffman_node **nodes, int count, int different)
|
||||||
{
|
{
|
||||||
int smallest;
|
// 'real' weights will always be positive.
|
||||||
|
int smallest = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; nodes[i]->weight == -1; i++);
|
for (i = 0; i < count; i++) {
|
||||||
|
|
||||||
if (i == different) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodes[i]->weight < nodes[smallest]->weight) {
|
if (smallest == -1 ||
|
||||||
|
nodes[i]->weight < nodes[smallest]->weight) {
|
||||||
smallest = i;
|
smallest = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +25,17 @@ find_smallest (struct huffman_node **nodes, int count, int different)
|
||||||
return smallest;
|
return smallest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shift_nodes (struct huffman_node **nodes, int count, int start)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = start; i + 1 < count; i++) {
|
||||||
|
nodes[i] = nodes[i + 1];
|
||||||
|
}
|
||||||
|
nodes[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct huffman_node *
|
struct huffman_node *
|
||||||
huffman_build_tree(void **values, int count)
|
huffman_build_tree(void **values, int count)
|
||||||
{
|
{
|
||||||
|
@ -52,24 +58,30 @@ huffman_build_tree(void **values, int count)
|
||||||
|
|
||||||
int tree1;
|
int tree1;
|
||||||
int tree2;
|
int tree2;
|
||||||
for (i = 1; i < count; i++) {
|
for (; count > 1; count--) {
|
||||||
struct huffman_node *tmp;
|
struct huffman_node *tmp;
|
||||||
|
|
||||||
tree1 = find_smallest (nodes, count, -1);
|
tree1 = find_smallest (nodes, count, -1);
|
||||||
tree2 = find_smallest (nodes, count, tree1);
|
tree2 = find_smallest (nodes, count, tree1);
|
||||||
|
|
||||||
tmp = nodes[tree1];
|
tmp = malloc (sizeof (struct huffman_node));
|
||||||
|
tmp->weight = nodes[tree1]->weight + nodes[tree2]->weight;
|
||||||
|
tmp->value = NULL;
|
||||||
|
tmp->left = nodes[tree1];
|
||||||
|
tmp->right = nodes[tree2];
|
||||||
|
|
||||||
nodes[tree1] = malloc (sizeof (struct huffman_node));
|
if (tree1 > tree2) {
|
||||||
nodes[tree1]->weight = tmp->weight + nodes[tree2]->weight;
|
shift_nodes (nodes, count, tree1);
|
||||||
nodes[tree1]->value = NULL;
|
shift_nodes (nodes, count, tree2);
|
||||||
nodes[tree1]->left = tmp;
|
} else {
|
||||||
nodes[tree1]->right = nodes[tree2];
|
shift_nodes (nodes, count, tree2);
|
||||||
|
shift_nodes (nodes, count, tree1);
|
||||||
nodes[tree2]->weight = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes[tree1];
|
nodes[count - 2] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
|
|
@ -68,8 +68,15 @@ class NodeQueue
|
||||||
node1 = self.find_smallest(-1)
|
node1 = self.find_smallest(-1)
|
||||||
node2 = self.find_smallest(node1)
|
node2 = self.find_smallest(node1)
|
||||||
new = merge_nodes(@nodes[node1], @nodes[node2])
|
new = merge_nodes(@nodes[node1], @nodes[node2])
|
||||||
@nodes[node1] = new
|
if node1 > node2
|
||||||
|
@nodes.delete_at(node1)
|
||||||
@nodes.delete_at(node2)
|
@nodes.delete_at(node2)
|
||||||
|
else
|
||||||
|
@nodes.delete_at(node2)
|
||||||
|
@nodes.delete_at(node1)
|
||||||
|
end
|
||||||
|
|
||||||
|
@nodes << new
|
||||||
end
|
end
|
||||||
@huffman_root = @nodes.first
|
@huffman_root = @nodes.first
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue