huffman coding

使用最小堆来快速访问最小元素

 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/

你可能感兴趣的:(Algorithms)