Simple Huffman encoder

/////////////////

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SCALE 1000
#define LINE 100
#define HEIGHT 20
typedef struct Node {
int count;
int value;
struct Node * left;
struct Node * right;
} Node;
typedef Node * PNode;
PNode stack[200];
int stack_index;
PNode top=0;
PNode new_node() {
PNode n = calloc(1,sizeof(Node));
return(n);
}
void swap(PNode p,PNode q){
Node  r = *p;
*p  = *q;
*q = r;

}

// Character graphcs set up and methods
char *init_screen(int width,int height){
int size=width*height;
char * p = malloc(size);
memset(p,' ',size);
return(p);
}

char * s_global;
void put_line( char *str) {
int i;
for(i=0;i < LINE;i++) {
putc(*str,stdout);
str++;
}
putc('\n',stdout);
}

void screen(char * str,int line) {
char s[LINE];
int j;
for(j=0;j < HEIGHT;j++)
put_line(str+j*LINE);
}


void bubble_once(PNode arr[], int n) {
int j;
      for (j = n-1; j >= 0; j--)
           if (arr[j]->count < arr[j+1]->count)
        swap(arr[j], arr[j+1]);
else
break;
}
void bubble_sort(PNode arr[], int n)
{
   int i;
   for (i = 0; i < n; i++)   
       bubble_once( arr,i); 
}


  // descend the graph
void descend(PNode o,int width,char* str,int d) {
sprintf(str+width/2, "%d",o->count);
str= str +  LINE; // Next line
d++;
if(o->left)  {
//printf("L %d %d %d\n", d, width,o->count);
descend(o->left,width/2,str,d);
}
if(o->right) {
//printf("R %d %d %d\n", d, width,o->count);
descend(o->right,width/2,str+width/2,d);
}
d--;
}

int push(PNode n,int index) {
stack[index]=n;
index++;
return(index);
}
int pop(PNode *n,int index) {
index--;
*n= stack[index];
return(index);
}


// Huffman stuff
int weight(PNode l, PNode r) {
int total = l->count+r->count;
int sum=(l->count * l->value + r->count * r->value);
return(sum/total);
}
int histogram(int value,int index) {
int i;
PNode n;
for(i=0;i < index;i++) {
if(stack[i]->value==value){
stack[i]->count++;
break;

}
if(i == index) {
n = new_node();
n->value=value;
n->count=1;
index=push(n,index);
}
return(index);
}
int huffman_tree(PNode stack[],int index) {
PNode l;
PNode r;
int i=0;
// Build Huffman tree from top of a node stack
while(index > 1) {

i++;
index=pop(&l,index);
index=pop(&r,index);
top = new_node();
index = push(top,index);
top->left=l;
top->right=r;                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
top->count=l->count+r->count;
top->value = weight(l,r);
bubble_once(stack,index-1);
}
if(index != 1) printf("Huffman error\n");
index = pop(&top,index);
return (index);
}
// Test with fake data
void printArray(PNode arr[], int size);
int main(void){
int i,value;
PNode o;
float x;
Node n;
char *str=init_screen(LINE,HEIGHT);
memset(stack,0,sizeof(stack));
// Build  data set for test
stack_index=0;
for(i=0; i < 256;i++) {
//value = (int) (SCALE * tanh(x));
value= rand() &0x1f;
stack_index= histogram(value, stack_index);  // Build histogram on the stack
//printf("Val %d %d\n",stack_index,value);
}
//printArray(stack,stack_index);
bubble_sort(stack,stack_index);  // Sort the stack of nodes by count
//printArray(stack,stack_index);
//printf("Stack Indx %d\n",stack_index);
stack_index=huffman_tree(stack,stack_index); // build encoder graph
printf("Stack Indxx %d\n",stack_index);
//printArray(stack,stack_index);
// Now descend from the top of the graph
descend(top,LINE,str,0);
screen(str,LINE);
free(str);
return 0;
}

// Test utility
// Function to print an array
void printArray(PNode arr[], int size)
{
    int i;
Node n;

    for (i=0; i < size; i++) {
n = *arr[i];
        printf("%d (%d %d) ;;  ", i,arr[i]->value,arr[i]->count);
        printf(" (%lx %lx)\n", arr[i]->left,arr[i]->right);
     
}
    printf("\n");
}

No comments: