哈夫曼译码器java_哈夫曼编码译码器及代码

本文介绍了一个使用C++实现的哈夫曼编码和译码系统,包括初始化、编码、译码等功能。该系统能读入字符集和权值,建立哈夫曼树,对文本进行编码和解码,提高信道利用率。
摘要由CSDN通过智能技术生成

编译环境:VC++ 6.0编程要求简述:

[问题描述]

利用哈夫曼编码进行信息通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双工信道

(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编译码系统。

[基本要求]

一个完整的系统应具有以下功能:

(l)I:初始化

(Initialization)。从终端读入字符集大小n,及n个字符和m个权值,建立哈夫曼树,并将它存于文件hfmtree中。

(2)C:编码

(Coding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmtree中读入),对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。

(3)D:编码

(Decoding)。利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中。

(4)P:印代码文件

(Print)。将文件codefile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。

(5)T:印哈夫曼树 (Tree

printing)。将已在内存中的哈夫曼树以直观的方式

(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。

程序源代码:

文件一:my.h(自定义头文件)

//调用有文件以及定义常数值

#include "stdio.h"

#include "string.h"

#define MAXLEN 100

#define MAXLEN_1 1000

//自定义类型声明

typedef struct

{

int weight;

char data;

int lchild,rchild,parent;

}HFMTnode;

typedef HFMTnode HFMT[MAXLEN];

typedef

struct

{

char code[MAXLEN];

char data;

}HFMCnode;

typedef HFMCnode HFMC[MAXLEN];

typedef

struct

{

char data[MAXLEN];

int top;

}seqstack;

//文件全局变量外部声明

extern int n;

//所有子函数声明

void InitializeTree(HFMT T);

void InputTree(HFMT T);

void Selectleast(HFMT T,int *p1,int *p2);

void CreateHFMT(HFMT T);

void push(char x);

void hfmc(HFMT T,int i);

void CreateHFMC(HFMT T,HFMC C);

void Initialization(HFMT T,HFMC C);

void Codeing(HFMC C);

void Decodeing(HFMC C);

void Showcodefile();

void Showhfmt(HFMT T);

int TreeDepth(HFMT T,int i);

void print(HFMT T,int i,int a);

文件二:Initialization.c(初始化)

#include

"my.h"

seqstack

s;

//初始化树

void InitializeTree(HFMT T)

{

int i;

printf("请输入要输入的字符个数n(n应大于1):");

scanf("%d",&n);

for(i=0;i<2*n-1;i++)

{

T.weight=-1;

T.lchild=-1;

T.rchild=-1;

T.parent=-1;

T.data='\0';

}

}

//输入树

void InputTree(HFMT T)

{

int i;

for(i=0;i

{

printf("请输入第%d个字符与权重:",i+1);

getchar();

scanf("%c %d",&T.data,&T.weight);

}

}

//从树数组中选取权值最小的两个元素

void Selectleast(HFMT T,int *p1,int *p2)

{

long min1,min2;

int i;

min1=min2=999999;

for(i=0;i<2*n-1;i++)

{

if(T.parent==-1&&T.weight!=-1)

if(T.weight

{

min1=T.weight;

*p1=i;

}

}

for(i=0;i<2*n-1;i++)

{

if(T.parent==-1&&T.weight!=-1)

if(T.weight

{

min2=T.weight;

*p2=i;

}

}

}

//构建哈夫曼树

void CreateHFMT(HFMT T)

{

int i,p1,p2;

InitializeTree(T);

InputTree(T);

for(i=n;i<2*n-1;i++)

{

Selectleast(T,&p1,&p2);

T.weight=T[p1].weight+T[p2].weight;

T.lchild=p1;

T.rchild=p2;

T[p1].parent=T[p2].parent=i;

}

}

//入栈

void push(char x)

{

s.top++;

s.data[s.top]=x;

}

//构建哈夫曼树编码库递归调用函数

void hfmc(HFMT T,int i)

{

int j;

j=T.parent;

if(j!=-1)

{

if(i==T[j].lchild)

push('0');

if(i==T[j].rchild)

push('1');

hfmc(T,j);

}

}

//构建哈夫曼树编码库

void CreateHFMC(HFMT T,HFMC C)

{

int i,j;

s.top=-1;

for(i=0;i

{

hfmc(T,i);

C.data=T.data;

for(j=0;s.top!=-1;j++)

{

C.code[j]=s.data[s.top];

s.top--;

}

C.code[j]='\0';

}

}

//初始化函数

void Initialization(HFMT T,HFMC C)

{

FILE *out;

int i;

CreateHFMT(T);

CreateHFMC(T,C);

if((out=fopen("hfmt.dat","w"))!=NULL)

{

fprintf(out,"%d",n);

for(i=0;i

fprintf(out,"%c",T.data);

for(i=0;i<2*n-1;i++)

fprintf(out,"\n%d %d %d

%d",T.weight,T.parent,T.lchild,T.rchild);

}

else

{

printf("\n文件打开错误!");

return;

}

fclose(out);

printf("\n初始化完毕!");

}

文件三:Codeing.c(编码)

#include

"my.h"

//编码函数

void Codeing(HFMC C)

{

FILE

*in,*out;

char zw[MAXLEN],code[MAXLEN_1];

int i=0,j,k,c_len,error=1;

c_len=0;//编码正文初始长度置零

//打开文件toberrans.dat并读取正文存入正文数组zw

if((in=fopen("tobetrans.dat","r"))!=NULL)

{

zw=fgetc(in);

while(feof(in)==0)

{

i++;

zw=fgetc(in);

}

zw='\0';

}

else

{

printf("\n文件打开错误!");

return;

}

fclose(in);

//进行编码

for(i=0;zw!='\0';i++)

{

error=1;//错误置为真

for(j=0;j

{

if(zw==C[j].data)

{

for(k=0;C[j].code[k]!='\0';k++)

{

code[c_len]=C[j].code[k];

c_len++;

}

error=0;//若编码库存在匹配字符,则错误为假

break;

}

}

if(error==1)

break;

}

code[c_len]='\0';

if(error)

{

printf("\n编码错误,请重新检查!");

return;

}

else

{

printf("\n正文为:%s",zw);

printf("\n编码为:%s",code);

//打开文件codefile.dat,并将编码正文写入文件

if((out=fopen("codefile.dat","w"))!=NULL)

fprintf(out,"%s",code);

else

{

printf("\n打开文件错误!");

return;

}

fclose(out);

printf("\n编码成功!");

}

}

文件四:Decodeing.c(译码)

#include

"my.h"

//译码函数

void Decodeing(HFMC C)

{

FILE *in,*out;

int i,j,k,c_max,c_len,dq,dq_len,flag,error=0;//error初始状态为假

char code[MAXLEN_1],a[MAXLEN],zw[MAXLEN];

code[0]='\0';

//打开文件codefile.dat,读取编码正文写入内存,存入数组code

if((in=fopen("codefile.dat","r"))!=NULL)

{

fscanf(in,"%s",code);

}

else

{

printf("\n打开文件错误!");

return;

}

fclose(in);

//求编码正文长度c_len

for(i=0;code!='\0';i++);

c_len=i;

if(c_len==0)

error=1;//错误情况1

//求编码库最长编码长度c_max

c_max=0;

for(i=0;i

{

for(j=0;C.code[j]!='\0';j++);

if(c_max

c_max=j;

}

//进行译码

dq=0; //dq用来记录code数组的读取位置

k=0; //k用来记录zw数组读取位置

while(dq

{

flag=1;

dq_len=c_max;

for(i=dq,j=0;j

a[j]=code;

a[j]='\0';

while(flag&&!error)//若无错误且flag为1则继续循环

{

for(i=0;i

{

if(strcmp(a,C.code)==0)

{

zw[k]=C.data;

k++;

flag=0;

break;

}

}//若找到编码库里匹配的编码,则结束循环

if(flag)

{

dq_len--;

a[dq_len]='\0';

}//未找到则将当前长度减一,继续寻找

if(dq_len<1)

error=1;//译码错误情况2

}

dq=dq+dq_len;//编码正文当前读取位置改变

}

zw[k]='\0';//在zw数组的最后一个位置添加字符串结束符

if(error)

{

printf("\n译码错误,请重新检查!");

return;

}

else

{

//打印编码正文以及译码正文

printf("\n编码为:%s",code);

printf("\n译码为:%s",zw);

//打开文件textfile.dat,将译码正文即数组zw写入文件

if((out=fopen("textfile.dat","w"))!=NULL)

fprintf(out,"%s",zw);

else

{

printf("\n打开文件错误!");

return;

}

fclose(out);

printf("\n译码成功!");

}

}

文件五:Showcodefile.c(显示代码文件)

#include

"my.h"

//显示编码文件内容函数

void Showcodefile()

{

FILE *in;

char code[MAXLEN_1];

int i;

code[0]='\0';

//打开文件

if((in=fopen("codefile.dat","r"))!=NULL)

{

fscanf(in,"%s",code);

}

else

{

printf("\n打开文件错误!");

return;

}

fclose(in);

//打印内容

printf("\n代码文件内容为:");

for(i=0;code!='\0';i++)

{

if(iP==0)

printf("\n");

printf("%c",code);

}

}

文件六:Showhfmt.c(以凹入法显示哈夫曼树)

#include

"my.h"

//求哈夫曼树深度函数

int TreeDepth(HFMT T,int i)

{

int ldep,rdep;

if(T.lchild==-1)

return 1;

else

{

ldep=TreeDepth(T,T.lchild);

rdep=TreeDepth(T,T.rchild);

if(ldep>rdep)

return ldep+1;

else

return rdep+1;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值