最近写了huffman树的编码及应用的小程序,希望对各位网友有点帮助
在将树存储到文件的过程中,没有使用xml或者将2种遍历存储来确定唯一的树,我使用了类似与先序遍历的递归方式
gcc编译通过 , 使用了一些linux的颜色的输出和系统调用 ,在 win的平台需要改下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Hashmax 26
typedef struct node{
int weight; /*表示权值*/
char data; /*表示字符*/
char code[100]; /*表示该字符的huffman编码*/
struct node *lchild,*rchild,*next;
}hufnode,*huftree;
/*用于建立散列表*/
typedef struct node2{
char key;
char code[100];
}HashNode;
HashNode hashtab[Hashmax]; /*全局变量*/
void inithash()
{
int i = 0;
char c[100] = {'/0'};
for (i = 0; i < Hashmax; i++){
hashtab[i].key = '/0';
strcpy(hashtab[i].code,c);
}
}
int hash_mod(int key)
{
return key % Hashmax;
}
void insert_hash(char key,char *code)
{
int index;
index = hash_mod(key);
hashtab[index].key = key;
strcpy(hashtab[index].code,code);
}
void showinterface()
{ printf("/n/n/n/n");
printf("/t/t/t/t/33[33m 1 input /n/33[37m");
printf("/t/t/t/t/33[32m 2 save /n/33[37m");
printf("/t/t/t/t/33[31m 3 read /n/33[37m");
printf("/t/t/t/t/33[30m 4 code /n/33[37m");
printf("/t/t/t/t/33[34m 5 recode /n/33[37m");
printf("/t/t/t/t/33[35m 6 exit /n/33[37m");
}
huftree insert(huftree root, huftree s)
{
huftree p1 = NULL, p2 = NULL;
if (root == NULL)
root = s;
else{
p1 = NULL;
p2 = root;
while (p2 && p2->weight < s->weight){
p1 = p2;
p2 = p2->next;
}
s->next = p2;
if (p1 == NULL)
root = s;
else
p1->next = s;
}
return root;
}
huftree createlist(huftree root, int size)
{
huftree s = NULL;
int i = 0;
while (size-- > 0){
s = (huftree)malloc(sizeof(hufnode));
printf("/33[33m please input the weight of hufnode/n/33[37m");
scanf("%d", &(s->weight));
getchar(); /*接受回车*/
printf("/33[33m please input the data of hufnode/n/33[37m");
scanf("%c", &(s->data));
getchar();
s->lchild = s->rchild = s->next = NULL;
root = insert(root, s);
}
return root;
}
huftree createhuffman(huftree root)
{
int i = 0;
huftree s = NULL, lc = NULL, rc = NULL;
while (root && root->next){
lc = root;
rc = root->next;
root = rc->next;
lc->next = NULL;
rc->next = NULL;
s = (huftree)malloc(sizeof(hufnode));
s->next = NULL;
s->weight = lc->weight + rc->weight;
s->data = '#';
for (i = 0; i < 100; i++)
lc->code[i] = rc->code[i] = s->code[i] = '/0';
s->lchild = lc;
s->rchild = rc;
root = insert(root,s);
}
return root;
}
void inorder(huftree root)
{
if (root){
inorder(root->lchild);
if(root->data != '#')
printf("%c %d %s/t", root->data,root->weight,root->code);
inorder(root->rchild);
}
}
void save(huftree root, FILE *fp)
{
if (root){
fprintf(fp,"%c%d",root->data,root->weight);
save(root->lchild, fp);
fprintf(fp,"%c%d", '$',0);
save(root->rchild, fp);
}
else{
return;
}
}
huftree rehuftree(int *i, int max, char *ad, int *aw)
{
int j;
if (*i < max){
if (aw[*i] != 0 && ad[*i] != '$'){
huftree tmp = (huftree)malloc(sizeof(hufnode));
tmp->rchild = tmp->lchild = tmp->next = NULL;
tmp->weight = aw[*i];
tmp->data = ad[*i];
/*将该节点编码置空*/
for (j = 0; j < 100; j++)
tmp->code[j] = '/0';
(*i)++;
tmp->lchild = rehuftree(i,max,ad,aw);
(*i)++;
tmp->rchild = rehuftree(i,max,ad,aw);
return tmp;
}
else
return NULL;
}
else
return NULL;
}
/*载入文件中的数据*/
huftree load(FILE *fp)
{
char ad[100]={'/0'};
int aw[100];
int i = 0;
int max = 0;
while (fscanf(fp,"%c%d",&ad[i],&aw[i])!=EOF){
i++;
}
max = i;
i = 0;
return rehuftree(&i,max-1,ad,aw);
}
/*编码每个huffman树节点*/
void sethuffmanencoding(huftree root,char *t,int k)
{
char tmp[100];
int len = strlen(t);
if (root){
strcpy(root->code,t);
if (k == 0)
root->code[len] = '0';
if (k == 1)
root->code[len] = '1';
sethuffmanencoding(root->lchild,root->code,0);
sethuffmanencoding(root->rchild,root->code,1);
}
else
return;
}
/*建立有序链表及huffman树*/
huftree Create(huftree root)
{
int size = 0;
while(size <= 0){
printf("/33[33m please input the number of huffman tree/n/33[37m");
scanf("%d",&size);
if (size <= 0){
printf("/33[33m please input the right number/n/33[37m");
size = 0;
continue;
}
else
break;
}
root = createlist(root, size);
root = createhuffman(root);
return root;
}
/*输出编码*/
void outputcode(char key)
{
int index = 0;
if (key >= 'a' && key <= 'z'){
index = hash_mod(key);
if (hashtab[index].key == '/0')
printf("no such key /n");
else{
printf("%s ",hashtab[index].code);
}
}
else
printf("no such key /n");
}
/*编码*/
void code(huftree root, char *c)
{
int i = 0;
printf("/33[33m please input the string you want to code/n/33[37m");
scanf("%s",c);
while (c[i] != '/0'&& i < 100){
outputcode(c[i]);
i++;
}
printf("/n/n");
getchar();
getchar();
return;
}
/*输出译码*/
void outputrecode(char *c,huftree root)
{
int i = 0;
printf("%s/t",c);
while (*(c+i) != '/0'){
if (root){
if (*(c+i) == '0')
root = root->lchild;
else if (*(c+i) == '1')
root = root->rchild;
}
i++;
}
if (root){
if (strcmp(root->code,c) == 0 && root->data != '#'){
printf("%c/n",root->data);
}
else
printf("no such code/n");
}
else
printf("no such code");
getchar();
}
/*译码*/
void recode(huftree root)
{
int i = 0;
int j = 0;
int n = 0;
char c[100][100]={'/0'};
if (root){
printf("/33[33m please input the number of code you want to recode/n/33[37m");
scanf("%d",&n);
printf("/33[33m please input the recode/33[37m");
for (j = 0; j < n; j++)
scanf("%s",c[j]);
while (i < n){
outputrecode(c[i],root);
i++;
}
}
else{
printf("/33[33m huffman tree is empty/n/33[37m ");
}
getchar();
getchar();
return;
}
void savecode(huftree root)
{
int index;
if (root){
if(root->data >= 'a' && root->data <= 'z'){
index = hash_mod(root->data);
hashtab[index].key = root->data;
strcpy(hashtab[index].code,root->code);
}
savecode(root->lchild);
savecode(root->rchild);
}
}
int main(int argc, char *argv[])
{
FILE *fp;
huftree root = NULL;
char key='/0';
char c[100]={'/0'};
inithash();
while(1){
key = '/6';
system("clear");
showinterface();
scanf("%c",&key);
getchar();
switch(key)
{
case '1':
root = Create(root);
sethuffmanencoding(root,"/0",-1);
savecode(root);
//inorder(root);
break;
case '2':
if ((fp=fopen("htmTree","w"))==NULL){
printf("cannot open file");
exit(0);
}
save(root,fp);
fclose(fp);
break;
case '3':
if((fp=fopen("htmTree","r"))==NULL){
printf("cannot open file");
exit(0);
}
root = load(fp);
fclose(fp);
sethuffmanencoding(root,"/0",-1);
savecode(root);
inorder(root);
break;
case '4':
code(root,c);
break;
case '5':
recode(root);
break;
case '6':
exit(0);
break;
}
}
return 0;
}