huffman encoding & decoding

#include <stdlib.h>
#include <stdio.h>

#define MAX_SIZE    100

struct data
{
    char character;
    int freq;
    struct data *left;
    struct data *right;
};

struct min_heap
{
    int heap_size;
    struct data *array[MAX_SIZE];
};

struct min_heap g_min_heap;

struct memory_pool
{
    void *ptr;
    int offset;
    int size;
};


char * g_table[26];

struct memory_pool g_memory_pool;


void build_min_heap( int size);
void decrease_key(int index, int key);
void get_encoded_text( struct data *root, char *encoded_text, int index);

void init_memory( int size )
{
    g_memory_pool.ptr = malloc( size );
    g_memory_pool.size = size;
    g_memory_pool.offset = 0;
}

struct data * allocate_memory( int size )
{
    if( g_memory_pool.offset >= g_memory_pool.size || g_memory_pool.offset + size >= g_memory_pool.size)
    {
        return NULL;
    }
    struct data * p = g_memory_pool.ptr + g_memory_pool.offset;
    g_memory_pool.offset += size;
    return p;
}

void init_heap(char * text)
{
    char alphabet[26] = {0, };
    //int count = 0;
    int k = 0;
    char *iter = text;
    while(*iter != '\0')
    {
        if(alphabet[*iter - 'a'] == 0 )
        {
            k++;
        }
        alphabet[*iter-'a'] ++;
        iter++;
    }

    init_memory(1024 * 1024 * 4);
    int i;
    for(i = 0; i < k; i++)
    {
        g_min_heap.array[i] = allocate_memory(sizeof(struct data));
    }

    int j = 0;
    for(i = 0; i < 26; i++)
    {
        if(alphabet[i] > 0)
        {
            g_min_heap.array[j]->character = i + 'a';
            g_min_heap.array[j]->freq = alphabet[i];
            j++;
        }
    }

    build_min_heap(j);
}


void min_heapify( int index)
{
    
    int left_index, right_index;
    int min_index;
    while(1)
    {
        left_index = 2 * index + 1;
        right_index = 2 * index + 2;

        if( left_index < g_min_heap.heap_size && g_min_heap.array[left_index]->freq < g_min_heap.array[index]->freq)
        {
            min_index = left_index;
        }
        else
        {
            min_index = index;
        }

        if( right_index < g_min_heap.heap_size && g_min_heap.array[right_index]->freq < g_min_heap.array[min_index]->freq)
        {
            min_index = right_index;
        }

        if(min_index != index)
        {
            struct data *tmp = g_min_heap.array[min_index];
            g_min_heap.array[min_index] = g_min_heap.array[index];
            g_min_heap.array[index] = tmp;
            index = min_index;    
        }
        else
        {
            break;
        }
    }
}

void build_min_heap( int size)
{
    g_min_heap.heap_size = size;
    int i;
    for( i = g_min_heap.heap_size / 2 - 1; i>= 0; i--)
    {
        min_heapify(i);
    }
}


void pop_min_data( struct data ** d)
{
    if(g_min_heap.heap_size < 1 )
    {
        *d = NULL;
        return;
    }

    *d = g_min_heap.array[0];
    g_min_heap.array[0] = g_min_heap.array[g_min_heap.heap_size - 1];
    g_min_heap.heap_size --;
    min_heapify( 0 );
}


void insert_data(struct data *d)
{
    struct data *tmp = d;
    int key = d->freq;
    tmp->freq = ((unsigned int)( 1 << 31) - 1);
    g_min_heap.heap_size ++;

    g_min_heap.array[g_min_heap.heap_size - 1] = tmp;

    decrease_key( g_min_heap.heap_size -1, key);
}


void decrease_key(int index, int key)
{
    if(g_min_heap.array[index]->freq <= key)
    {
        return;
    }

    g_min_heap.array[index]->freq = key;

    int parent_index = index / 2 - 1;

    while( parent_index >= 0 && g_min_heap.array[parent_index]->freq > g_min_heap.array[index]->freq)
    {
        struct data *tmp = g_min_heap.array[index];
        g_min_heap.array[index] = g_min_heap.array[parent_index];
        g_min_heap.array[parent_index] = tmp;

        parent_index = index / 2 - 1;
    }
}

struct data * build_huffman_code( void)
{
    int i = 0;
    int size = g_min_heap.heap_size;
    while( i < size - 1 )
    {
        struct data *left, *right;
        pop_min_data(&left);
        pop_min_data(&right);
    
        struct data *new_data = allocate_memory(sizeof(struct data));
        new_data->freq = left->freq + right->freq;
        new_data->left = left;
        new_data->right = right;
        new_data->character = '\0';
        insert_data(new_data);
        i++;        
    }

    struct data *root = NULL;
    pop_min_data(&root);
    
    return root;
}

void get_encoded_text1( struct data *root, char *encoded_text, int index)
{
    if(root->left)
    {
        encoded_text[index] = '0';
        get_encoded_text(root->left, encoded_text, index + 1);
    }

    if(root->right)
    {
        encoded_text[index] = '1';
        get_encoded_text(root->right, encoded_text, index + 1);
    }

    if( root->left == NULL && root->right == NULL)
    {
        if( g_table[root->character - 'a'] == NULL )
        {
            g_table[root->character -'a'] = (char *)allocate_memory( index + 1 );
        }
        
        int i;
        for( i = 0; i < index; i++)
        {
            g_table[root->character - 'a'][i] = encoded_text[i];
        }

        g_table[root->character -'a'][i] = '\0';
        printf("%c: ---> %s\n", root->character, g_table[root->character-'a']);
    }
}

void get_encoded_text( struct data* root, char *encoded_text, int index)
{
    if(root == NULL)
    {
        return;
    }
    if(root->character != '\0')
    {
        
        if( g_table[root->character - 'a'] == NULL )
        {
            g_table[root->character -'a'] = (char *)allocate_memory( index + 1 );
        }
        
        int i;
        for( i = 0; i < index; i++)
        {
            g_table[root->character - 'a'][i] = encoded_text[i];
        }

        g_table[root->character -'a'][i] = '\0';
    }

    encoded_text[index] = '0';
    get_encoded_text(root->left, encoded_text, index +1);
    encoded_text[index] = '1';
    get_encoded_text(root->right, encoded_text, index +1);
}
void construct_encoding_table( struct data *root )
{
    char encoded_text[100];
    get_encoded_text(root, encoded_text, 0);
}
/*
void decode_string_one_char(struct data *root, char *input, char *output, int *in_index, int *out_index)
{
    struct data *iter = root;
    while( input[*in_index] != '\0' && iter )
    {
        if( input[*in_index] == '0' )
        {
            iter = iter->left;
        }
        else
        {
            iter = iter->right;
        }

        if( iter == NULL )
        {
            return;
        }
        if( iter && iter->left == NULL && iter->right == NULL)
        {
            output[*out_index] = iter->character;
            (*out_index)++;
            (*in_index)++;
            return;
        }
        (*in_index)++;
    }
}
*/

void decode_string(struct data *root, char *input, char *output)
{    
/*    int in_index = 0, out_index = 0;
    while( input[in_index] != '\0')
    {
        decode_string_one_char(root, input, output, &in_index, &out_index);
    }

    output[out_index] = '\0';*/

    char * iter = input;
    struct data *tree_iter = root;
    int i = 0;
    while(*iter != '\0')
    {
        if(*iter == '0')
        {
            tree_iter = tree_iter->left;
        }
        else
        {
            tree_iter = tree_iter->right;
        }

        if(tree_iter->left == NULL && tree_iter->right == NULL)
        {
            output[i] = tree_iter->character;
            i++;
            tree_iter = root;
        }
        iter++;
    }

    output[i] = '\0';
}

int main(void)
{
    char * text = "geeksforgeeks";
    init_heap(text);
    struct data *root = build_huffman_code();    
    construct_encoding_table(root);

    char encoded_text[100];
    int i = 0;
    char *iter = text;
    while(*iter)
    {
        char *tmp = g_table[*iter-'a'];
        while(*tmp != '\0')
        {
            encoded_text[i] = *tmp;
            tmp++;
            i++;
        }
//        printf("%s", g_table[*iter-'a']);
        iter++;
    }

    encoded_text[i] = '\0';
    printf("%s\n", encoded_text);

    char output_text[100];
    decode_string(root, encoded_text, output_text);
    printf("%s\n", output_text);
    return 0;
}

https://www.geeksforgeeks.org/huffman-decoding/

猜你喜欢

转载自blog.csdn.net/CaspianSea/article/details/83934799