使用最小堆来快速访问最小元素
min_priority_queue.h:
#ifndef __MIN_PRIOIRTY_QUEUE_H__
#define __MIN_PRIORITY_QUEUE_H__
struct min_priority_item
{
char value;
int key;
struct min_priority_item * left;
struct min_priority_item * right;
};
int min_priority_queue_init(int * key, char *value, int size);
int min_priority_queue_size( void );
int min_priority_queue_build( void );
struct min_priority_item * min_priority_queue_extract_min( void );
int min_priority_queue_insert( struct min_priority_item * item );
void min_priority_queue_fini( void );
#endif //__MIN_PRIORITY_QUEUE_H__
min_priority_queue.c:
#include "min_priority_queue.h"
#include
struct min_priority_queue
{
int capacity;
int heap_size;
struct min_priority_item ** items;
};
struct min_priority_queue g_queue;
int min_priority_queue_init( int *key, char *value, int size)
{
g_queue.items = (struct min_priority_item **)malloc(size * sizeof(struct min_priority_item *));
g_queue.heap_size = 0;
g_queue.capacity = size;
int i;
for( i = 0; i < size; i++)
{
g_queue.items[i] = (struct min_priority_item *)malloc(sizeof(struct min_priority_item));
g_queue.items[i]->key = key[i];
g_queue.items[i]->value = value[i];
}
return 0;
}
int min_priority_queue_size( void )
{
return g_queue.heap_size;
}
void min_heapify( int index )
{
int parent_index = index;
int left_child_index;
int right_child_index;
int minimal_index, minimal_key;
struct min_priority_item *check_item = g_queue.items[index];
while( 1)
{
left_child_index = parent_index * 2 + 1;
right_child_index = left_child_index + 1;
if( left_child_index < g_queue.heap_size && g_queue.items[left_child_index]->key < check_item->key )
{
minimal_index = left_child_index;
minimal_key = g_queue.items[left_child_index]->key;
}
else
{
minimal_index = parent_index;
minimal_key = check_item->key;
}
if( right_child_index < g_queue.heap_size && g_queue.items[right_child_index]->key < minimal_key )
{
minimal_index = right_child_index;
}
if( minimal_index != parent_index )
{
g_queue.items[parent_index] = g_queue.items[minimal_index];
parent_index = minimal_index;
}
else
{
g_queue.items[parent_index] = check_item;
break;
}
}
}
int build_min_heap( void )
{
int i;
g_queue.heap_size = g_queue.capacity;
for( i = (g_queue.heap_size - 1 ) / 2; i >= 0; i--)
{
min_heapify( i );
}
return 0;
}
int min_priority_queue_build( void )
{
return build_min_heap();
}
/*
int min_priority_queue_decrease_key( int index, int key)
{
if( index >= g_queue.heap_size || g_queue.items[index]->key <= key )
{
return -1;
}
g_queue.items[index].key = key;
int parent_index = (index -1) / 2;
while( parent_index < g_queue.heap_size && parent_index >= 0 && g_queue.items[parent_index]->key > g_queue.items[index],key )
{
struct min_priority_item * tmp = g_queue.items[parent_index];
g_queue.items[parent_index] = g_queue.items[index];
g_queue.items[index] = tmp;
index = parent_index;
parent_index = (index -1) / 2;
}
return 0;
}*/
int min_priority_queue_insert( struct min_priority_item * item )
{
g_queue.heap_size ++;
g_queue.items[g_queue.heap_size -1] = item;
int index = g_queue.heap_size - 1;
int parent_index = (index - 1) / 2;
while( parent_index < g_queue.heap_size && parent_index >= 0 && g_queue.items[parent_index]->key > g_queue.items[index]->key )
{
struct min_priority_item * tmp = g_queue.items[parent_index];
g_queue.items[parent_index] = g_queue.items[index];
g_queue.items[index] = tmp;
index = parent_index;
parent_index = (index -1) / 2;
}
return 0;
}
struct min_priority_item * min_priority_queue_extract_min( void )
{
if( g_queue.heap_size <= 0 )
{
return NULL;
}
struct min_priority_item * item = g_queue.items[0];
g_queue.items[0] = g_queue.items[g_queue.heap_size - 1];
g_queue.heap_size --;
min_heapify( 0 );
return item;
}
void min_priority_queue_fini( void )
{
if(g_queue.items)
{
free(g_queue.items);
}
}
test.c:
#include "min_priority_queue.h"
#include
#include
struct min_priority_item * build_huffman_tree()
{
int size = min_priority_queue_size();
int i;
for( i = 0; i < size - 1; i++)
{
struct min_priority_item * item = (struct min_priority_item *)malloc(sizeof(struct min_priority_item));
struct min_priority_item *left_child = min_priority_queue_extract_min();
struct min_priority_item *right_child = min_priority_queue_extract_min();
item->key = 0;
item->value = '$';
if(left_child)
{
item->key += left_child->key;
}
if(right_child)
{
item->key += right_child->key;
}
item->left = left_child;
item->right = right_child;
min_priority_queue_insert( item );
}
return min_priority_queue_extract_min();
}
void print_binary_bit( struct min_priority_item * root, char bit[], int index)
{
if( root->left )
{
bit[index] = '0';
print_binary_bit( root->left, bit, index + 1);
}
if(root->right)
{
bit[index] = '1';
print_binary_bit( root->right, bit, index + 1);
}
if( !root->left && !root->right )
{
printf("%c: ", root->value);
int i;
for( i = 0; i < index; i++)
{
printf("%c", bit[i]);
}
printf("\n");
}
}
void free_memory( struct min_priority_item * root)
{
struct min_priority_item * left = root->left;
struct min_priority_item * right = root->right;
free(root);
if( left )
{
free_memory(left);
}
if(right)
{
free_memory(right);
}
}
int main(void )
{
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
int freq[] = { 5, 9, 12, 13, 16, 45 };
min_priority_queue_init( freq, arr, sizeof(arr)/sizeof(arr[0]));
min_priority_queue_build();
struct min_priority_item * root = build_huffman_tree();
char bit[10] = {'\0', };
print_binary_bit( root, bit, 0 );
free_memory(root);
min_priority_queue_fini();
return 0;
}
输出:
f: 0
c: 100
d: 101
a: 1100
b: 1101
e: 111
参考:
https://www.geeksforgeeks.org/huffman-coding-greedy-algo-3/