#include
#include
#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/