哈夫曼编码与解码

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


#define MAXNUM 60  


typedef struct
{
char ch;
int weight; //权值,这个字符出现的频率  
int parent;
int left;
int right;
}HuffNode;


typedef struct
{
char code[MAXNUM];
int start;
}HuffCode;


HuffNode ht[MAXNUM * 2]; //存放哈夫曼树  


HuffCode hcd[MAXNUM];  //存放ht数组中对应的字符的编码  


int n;                 //字符的个数  


//初始化哈夫曼树ht  
void initHt()
{
FILE * fp;
char ch;
int i = 0;
//从文件frequency.txt中读出要编码的字符和权值  
if ((fp = fopen("frequency.txt", "r")) == NULL){
printf("can not open the file character.txt");
exit(0);
}
ht[i].left = ht[i].right = ht[i].parent = -1;
while ((ch = fgetc(fp)) != EOF){
if (ch == '\n'){
i++;
ht[i].left = ht[i].right = ht[i].parent = -1;
}
else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
ht[i].ch = ch;
else if (ch >= '0'&&ch <= '9')
ht[i].weight = ht[i].weight * 10 + ch - '0';
}
n = i + 1;
if (fclose(fp)){
printf("can not close the file character.txt");
exit(0);
}
}


//构造哈夫曼树,看成有n棵树,选择权值最小的两棵树合并  
void createHuffTree()
{


int i = 0, k;
int minI, minJ;
int f = 0;
minI = minJ = -1; //minI<minJ  
for (k = n; k<2 * n - 1; k++){
//寻找ht中权值最小且无父结点的两个结点  
i = 0;
f = 0;
while (ht[i].ch != '\0'){
if (ht[i].parent == -1){
if (f == 0){
minI = i;
f++;
}
else if (f == 1){
if (ht[i].weight<ht[minI].weight){
minJ = minI;
minI = i;
}
else
minJ = i;
f++;
}
else{
if (ht[i].weight<ht[minI].weight){
minJ = minI;
minI = i;
}
else if (ht[i].weight<ht[minJ].weight)
minJ = i;
}
}
i++;
}
//合并两个结点  
ht[k].ch = '#';
ht[k].left = minI;
ht[k].right = minJ;
ht[k].weight = ht[minI].weight + ht[minJ].weight;
ht[k].parent = -1;
ht[minI].parent = ht[minJ].parent = k;
}
}


//将一个字符串反转  
void reverse(char *str)
{
int i, j;
char ch;
for (i = 0, j = strlen(str) - 1; i<j; i++, j--){
ch = str[i];
str[i] = str[j];
str[j] = ch;
}
}
char str[15];
char *code[50];
//哈夫曼编码,通过父节点从下往上找  
void createHuffCode()
{
int i, j, length;
FILE * fp,*fp1;
for (i = 0; i<n; i++){
length = 0;
j = i;
//给每个字符进行编码  
while (ht[j].parent != -1){
if (ht[ht[j].parent].left == j){
hcd[i].code[length++] = 0 + '0';
}
else
hcd[i].code[length++] = 1 + '0';
j = ht[j].parent;
}


hcd[i].start = hcd[i].code[length - 1] - '0';
hcd[i].code[length] = '\0';
reverse(hcd[i].code);
}
//把hcd字符编码写入文件codes.txt中  
if ((fp = fopen("codes.txt", "w")) == NULL){
printf("can not open the file character.txt");
exit(0);
}
if ((fp1= fopen("continue code.txt", "w")) == NULL){
printf("can not open the file character.txt");
exit(0);
}
for (i = 0; i<n; i++){
fputc(ht[i].ch, fp);
str[i] = ht[i].ch;
fputs("    ", fp);
fputs(hcd[i].code, fp);
code[i] = hcd[i].code;
fputc('\n', fp);
fputs(hcd[i].code, fp1);
}
if (fclose(fp)){
printf("can not close the file character.txt");
exit(0);
}
}


//哈夫曼解码,每次都从根节点开始搜索  
int releaseHuffCode(char *str, char* code)
{
FILE*fp3 = fopen("message.txt", "w");
if (!fp3)
printf("Error!\n");
int root = 2 * n - 2;
int length = 0, i = 0;
while (code[i]){
if (code[i] == '0' + 0)
{
root = ht[root].left;

}
else if (code[i] == '0' + 1)
{ root = ht[root].right;

}
else
return 0;
if (ht[root].left == -1 && ht[root].right == -1){
str[length++] = ht[root].ch;
root = 2 * n - 2;
fputs(str, fp3);
}
i++;
}
str[length] = '\0';
if (root == 2 * n - 2)
return 1;

return 0;
}


//主函数  
void main()
{
initHt();
createHuffTree();
createHuffCode();
releaseHuffCode(str, *code);
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值