您的位置:首页 > 其它

赫夫曼树和赫夫曼编码

2015-10-25 19:48 323 查看
#include <stdio.h>

#define MAXSIZE 128
//字符表
typedef struct {
char ch;
unsigned int repeat;
}table;

//哈夫曼树节点
typedef struct {
char data;
unsigned int weight;
int  parent,lchild, rchild;
}hfmtree;

//哈夫曼编码
typedef struct {
char data;
char code[128];
}hfmcode;

hfmtree Hdata[2*MAXSIZE-1];
hfmcode code[MAXSIZE];
int count = 0;

void insrtch(char str[],char ch){//字符串首端插入字符
int len = 0;
while(str[len]!='\0'){
len++;
}
str[len+1] = '\0';
while(len!=0){
str[len] = str[len-1];
len--;
}
str[0] = ch;
}

int length(char *str){//求字符串长度
int len = 0;
while(str[0]!='\0'){
len ++;
str++;
}
return len;
}

int Getext(){//读文本文件,获取字符重复次数,存入字符表
FILE *fp;
int i,p;
char buf;
count = 0;
table tb[MAXSIZE]={0};
fopen_s(&fp,"d:\\text.txt","r");
while(fread(&buf,1,1,fp)){
printf("%c",buf);
p = (int)buf;
tb[p].ch = buf;
(tb[p].repeat) ++;
}
fclose(fp);
//赫夫曼森林种树
for(i=0;i<MAXSIZE;i++){
if(tb[i].repeat !=0){
Hdata[count].data=tb[i].ch;
Hdata[count].weight=tb[i].repeat;
count++;
}
}
//打印字符表
printf_s("\nNow,Output the Text Table......\n");
getchar();
for(i=0;i<count;i++){
printf("%d,%c,%u\n",i,Hdata[i].data,Hdata[i].weight);
}
return 0;
}

int BuildTree(){//建立哈夫曼树
int i, j, k = 0;
int reset = 0;
int tnum = 0;
int p1 = count;
unsigned int  small = 65636 ;
for (i=0;i<2*count-2 ;i++){
for (j = 0; j < p1; j++){
if(Hdata[j].parent==-1) tnum++;
if ((Hdata[j].weight < small )&& (Hdata[j].parent == -1)) {
small = Hdata[j].weight ;
k = j;
}
}
if (reset == 0){
Hdata[p1].weight += Hdata[k].weight ;
Hdata[p1].lchild = k;
Hdata[k].parent = p1;
reset = 1;
}
else{
Hdata[p1].weight += Hdata[k].weight ;
Hdata[p1].rchild = k;
Hdata[k].parent = p1;
reset = 0;
p1++;
}
if (tnum<2) break;
tnum=0;
small = 65636;
}
printf_s("\nNow,Output the Huffman Tree......\n");
getchar();
for(i=0;i<2*count-1;i++)
printf("%d: %c,%u,%d,%d,%d\n",i,Hdata[i].data,Hdata[i].weight,Hdata[i].parent , Hdata[i].lchild,Hdata[i].rchild );
return 0;
}

int Code(){//生成前缀编码
int i;
printf_s("\nNow,Output the Huffman Code......\n");
getchar();
int  c, p;
for (i = 0; i < count; i++){
code[i].data =  Hdata[i].data ;
code[i].code[0] =  '\0' ;
c = i;
p = Hdata[c].parent;
while (p != -1){
if (Hdata[p].lchild == c) insrtch(code[i].code,'0');
else insrtch(code[i].code,'1');
c = p;
p = Hdata[c].parent;
}
}
for (i = 0; i < count; i++){
printf("%c: %s\n",code[i].data,code[i].code);
}
return 0;
}

int Encode(){//对文本文件编码
FILE *fpr,*fpw;
int i;
char ch ,*str;
fopen_s(&fpr,"d:\\text.txt","r");
fopen_s(&fpw,"d:\\code.txt","w");
while(fread(&ch,sizeof(char),1,fpr)){
for (i=0;i<count;i++){
if(code[i].data == ch){
str =  code[i].code;
fwrite(str,sizeof(char),length(str),fpw);
break;
}
}
}
printf("\n");
fclose(fpr);
fclose(fpw);
return 0;
}

int Decode(){//文本文件存储的二进制码解码
FILE *fp;
int i,m;
char buf;
printf_s("\nNow,We can decode a binary string read from a text file......\n");
getchar();
fopen_s(&fp,"d:\\code.txt","r");
m = 2*count- 1;
i = m -1;
while(fread(&buf,1,1,fp)){
if (buf == '0') i = Hdata[i].lchild;
else i = Hdata[i].rchild;

if (Hdata[i].lchild == -1){
printf_s("%c",Hdata[i].data);
i = m -1;
}
}
fclose(fp);
printf_s("\nCongratulations! We Success !\n");
return 0;
}

int main(){
for(int i = 0;i<2*MAXSIZE-1;i++){//初始化赫夫曼树
Hdata[i].data='0';
Hdata[i].weight=0;
Hdata[i].parent=-1;
Hdata[i].lchild=-1;
Hdata[i].rchild=-1;
}

Getext();//获得字符重复次数
BuildTree();//建立赫夫曼二叉树,数组存储
Code();//前缀编码
Encode();//对一串文字进行编码,保存到文本文件
Decode();//对输入的一个或一串编码进行解码
getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: