Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Huffman algorithm using c programming and data structures #60

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions compression/huffman/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
project: main.o compress.o decompress.o heap.o table.o tree.o
cc main.o compress.o decompress.o heap.o table.o tree.o -o project -Wall
main.o: main.c heap.h
cc -c main.c -Wall
compress.o: compress.c heap.h
cc -c compress.c -Wall
decompress.o: decompress.c tree.h
cc -c decompress.c -Wall
heap.o: heap.c heap.h
cc -c heap.c -Wall
table.o: table.c table.h
cc -c table.c -Wall
tree.o: tree.c tree.h
cc -c tree.c -Wall
9 changes: 9 additions & 0 deletions compression/huffman/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
compression algorithms
1) hoffman coding
* read file and count the freq of each char
* create tree of each char and add it in heap with pseudo eof as well
* create a whole tree form taking 2 tree from heap continuously until we remain with one tree in heap
* create hash table from tree
* write compressed file

2) lzw
194 changes: 194 additions & 0 deletions compression/huffman/compress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include"heap.h"

#define MAX 257

void preorder(tree* t, int* arr, int* n){
if(*t == NULL)
return;
if((*t)->left == (*t)->right)
arr[(*n)++] = 1;
else
arr[(*n)++] = 0;
preorder(&((*t)->left), arr, n);
preorder(&((*t)->right), arr, n);
}
void writeleaves(tree* t, int fdw){
if(*t == NULL)
return;
if((*t)->left == NULL && (*t)->right == NULL){
write(fdw, &((*t)->d.ch), sizeof(char));
}
writeleaves(&((*t)->left), fdw);
writeleaves(&((*t)->right), fdw);
}
void header(int fdw, int* arr, int n){
int i;
int bits = 0;
unsigned char w;
for(i = 0; i < n; i++){
if(arr[i] == 1){
w = w | 0x01;
}
else if(arr[i] == 0)
w = w & 0xfe;
bits++;
if(bits == 8){
write(fdw, &w, sizeof(char));
bits = 0;
w = '\0';
}
else
w = w << 1;
}
char last = bits + '0';
if(bits < 8){
while(bits < 7){
w = w & 0xfe;
w = w << 1;
bits++;
}
write(fdw, &w, sizeof(char));
}
char no = '\0';
write(fdw, &last, sizeof(char));
write(fdw, &no, sizeof(char));
}
/*void header(int fdw, tree* t, char w){
unsigned char eof = 256;
static int i = 0;
if(*t == NULL)
return;
if((*t)->isleaf == 1){
w = w | 0x01;
i++;
if(i == 8){
write(fdw, &w, sizeof(char));
i = 0;
w = '\0';
}
else{
w = w << 1;
}
}
else if((*t)->isleaf == 0){
w = w & 0xfe;
i++;
if(i == 8){
write(fdw, &w, sizeof(char));
i = 0;
w = '\0';
}
else{
w = w << 1;
}
}
header(fdw, &((*t)->left), w);
header(fdw, &((*t)->right), w);
if(i < 8){
while(i < 8){
w = w & 0xfe;
i++;
}
write(fdw, &w, sizeof(char));
}
write(fdw, &eof, sizeof(char));
}
void header2(int fdw, tree* t){
if(*t == NULL)
return;
if((*t)->isleaf == 1){
write(fdw, &((*t)->d.ch), sizeof(char));
}
header2(fdw, &((*t)->left));
header2(fdw, &((*t)->right));
write(fdw, '\0', sizeof(char));
}*/
int compress(int fdr, int fdw, table* th, tree* t){
int index, j = 0, len;
unsigned char ch, str[1000], wrtbyte;
int arr[1024];
int n = 0;
preorder(t, arr,&n);
header(fdw, arr, n);
writeleaves(t, fdw);
int c = 0;
int bits = 0;
while((n = read(fdr, &ch, sizeof(char)))){
c++;
index = (int)ch;
strcpy((char*)str, th[index].str);
len = strlen((char*)str);
j = 0;
while(j < len){
if(str[j] == '1'){
wrtbyte = wrtbyte | 0x01;
}
else if(str[j] == '0'){
wrtbyte = wrtbyte & 0xfe;
}
bits++;
if(bits == 8){
write(fdw, &wrtbyte, sizeof(char));
bits = 0;
wrtbyte = '\0';
}
else{
wrtbyte = wrtbyte << 1;
}
j++;
}
}
char last = bits + '0';
if(bits < 8){
while(bits < 7){
wrtbyte = wrtbyte & 0xfe;
wrtbyte = wrtbyte << 1;
bits++;
}
if(wrtbyte != '\0')
write(fdw, &wrtbyte, sizeof(char));
}
write(fdw, &last, sizeof(char));
return c;
}
tree initial(int fdr, table *th){
data d[MAX];
tree t1, t2, t3, t4;
heap h;
InitHeap(&h);
int i, c2 = 0;
for(i = 0; i < MAX; i++)
d[i].count = 0;
unsigned char ch;
int index;
while(read(fdr, &ch, sizeof(char))){
index = (int)ch;
d[index].ch = ch;
d[index].count++;
}
for(i = 0; i < MAX; i++){
if(d[i].count != 0){
t1 = CreateTreeOfOneNode(d[i]);
InsertInHeap(&h, &t1);
c2++;
}
}
while(!IsHeapEmpty(&h)){
if(!IsHeapEmpty(&h))
t2 = RemoveFromHeap(&h);
if(!IsHeapEmpty(&h))
t3 = RemoveFromHeap(&h);
else{
break;
}
t4 = CreateTreeFromTwoTree(&t2, &t3);
InsertInHeap(&h, &t4);
}
char str[1024];
CreateTable(th, &t2, str, 0);
return t2;
}
126 changes: 126 additions & 0 deletions compression/huffman/decompress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include"tree.h"
void getpreorder(int fdr, int* arr, int* n){
unsigned char ch, next, nextkanext;
int i = 0, j, k;
read(fdr, &ch, sizeof(char));
read(fdr, &next, sizeof(char));
while(read(fdr, &nextkanext, sizeof(char))){
if(nextkanext == '\0')
break;
while(i < 8){
k = ch & 0x80;
if(k == 0)
arr[(*n)++] = 0;
else if(k != 0)
arr[(*n)++] = 1;
ch = ch << 1;
i++;
}
i = 0 ;
ch = next;
next = nextkanext;
}
int use = next - '0';
for(j = 0; j < use; j++){
k = ch & 0x80;
if(k == 0)
arr[(*n)++] = 0;
else if(k != 0)
arr[(*n)++] = 1;
ch = ch << 1;
}
}
tree buildtreeconti(int* arr, int* index, int n){
int in = *index;
if(in == n)
return NULL;
node* tmp = (node*)malloc(sizeof(node));
tmp->isleaf = arr[in];
tmp->left = tmp->right = NULL;
(*index)++;
if(arr[in] == 0){
tmp->left = buildtreeconti(arr, index, n);
tmp->right = buildtreeconti(arr, index, n);
}
return tmp;
}
tree buildtree(int*arr, int n){
int index = 0;
return buildtreeconti(arr, &index, n);
}
void giveleaves(tree* t, int fdr){
if(*t == NULL)
return;
if((*t)->left == NULL && (*t)->right == NULL){
unsigned char ch;
read(fdr, &ch, sizeof(ch));
(*t)->d.ch = ch;
}
giveleaves(&((*t)->left), fdr);
giveleaves(&((*t)->right), fdr);
}
void decode(int fdr, int fdw, tree* t){
node* p = *t;
int i = 0, j, k;
unsigned char ch, next, nextkanext;
read(fdr, &ch, sizeof(char));
read(fdr, &next, sizeof(char));
while(read(fdr, &nextkanext, sizeof(char))){
while(i < 8){
k = ch & 0x80;
if(k == 0){
if(p->left == p->right){
write(fdw, &(p->d.ch), sizeof(p->d.ch));
p = *t;
}
p = p->left;
ch = ch << 1;
}
else if(k != 0) {
if(p->left == p->right){
write(fdw, &(p->d.ch), sizeof(p->d.ch));
p = *t;
}
p = p->right;
ch = ch << 1;
}
i++;
}
i = 0 ;
ch = next;
next = nextkanext;
}
int use = next - '0';
for(j = 0; j < use; j++){
k = ch & 0x80;
if(k == 0){
if(p->left == p->right){
write(fdw, &(p->d.ch), sizeof(p->d.ch));
p = *t;
}
p = p->left;
ch = ch << 1;
}
else if(k != 0){
if(p->left == p->right){
write(fdw, &(p->d.ch), sizeof(p->d.ch));
p = *t;
}
p = p->right;
ch = ch << 1;
}
}
write(fdw, &(p->d.ch), sizeof(p->d.ch));
}
void decompress(int fdr, int fdw){
int arr[1024], n = 0, i;
getpreorder(fdr, arr, &n);
tree t;
t = buildtree(arr, n);
giveleaves(&t, fdr);
decode(fdr, fdw, &t);
}
Loading