70,037
社区成员
发帖
与我相关
我的任务
分享#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef char datatype;
typedef struct
{
int weight;
datatype data;
int lchild,rchild,parent;
}hufmtree;//Huffman树的储存表示
typedef struct
{
char bits[50];
int start;
datatype data;
}codetype;//Huffman编码的储存表示
int DEPTH=0;
void CreateHUFMT(hufmtree *tree,int n,codetype *code)
{//创建huffman树,求出n个字符的huffman编码
int i,j,p1,p2,small1,small2,m;
char ch;
m=2*n-1;
for(i=0;i<m;i++)
{
tree[i].lchild=(-1); tree[i].rchild=(-1);
tree[i].parent=(-1); tree[i].weight=(-1);
tree[i].data='0';
}
for(i=1;i<=n;i++)
{
while((getchar())!='\n');
printf("请输入第%d个字符及权值(格式:字符 权值):",i);
scanf("%c %d",&tree[i-1].data,&tree[i-1].weight);
}
for(i=n;i<m;i++)
{
p1=p2=0;small1=small2=1000;
for(j=0;j<=i-1;j++)
if(tree[j].parent==(-1))
if(tree[j].weight<small1)
{small2=small1;
small1=tree[j].weight; p2=p1; p1=j;
}
else if(tree[j].weight<small2)
{small2=tree[j].weight; p2=j;}
tree[p1].parent=tree[p2].parent=i;
tree[i].lchild=p1;
tree[i].rchild=p2;
tree[i].weight=tree[p1].weight+tree[p2].weight;
}
int c,p;
codetype *cd;
cd=(codetype*)malloc(n*sizeof(codetype));
for(i=0;i<n;i++)
{
cd[i].start=n; c=i;
p=tree[c].parent;
cd[i].data=tree[c].data;
while(p!=(-1))
{
cd[i].start--;
if(tree[p].rchild==c) cd[i].bits[cd[i].start]='1';
else cd[i].bits[cd[i].start]='0';
c=p;
p=tree[c].parent;
}
for(int s=0;s<cd[i].start;s++)cd[i].bits[s]='#';
code[i]=cd[i];
}
free(cd);
}
//***************************编译码*****************************//
void Decode(hufmtree *tree,char*size,int n)
{
int i,j,k;
char p[100];
printf("请输入需要译码的代码:");
getchar();
gets(p);
i=2*n-2; k=0;
for(j=0;p[j]!='\0';j++)
{
if(p[j]=='0')i=tree[i].lchild;
else i=tree[i].rchild;
if(tree[i].lchild==(-1))
{size[k++]=tree[i].data;
i=2*n-2;
}
}
size[k]='\0';
}
void Encode(codetype code[],char*coding,int n)
{
int i,j,t,k=0;
char p[100];
printf("请输入需要编码的文本:");
getchar();
gets(p);
for(i=0;p[i]!='\0';i++)
{
if((p[i]>='A'&&p[i]<='Z')||p[i]==' ')
for(j=0;j<=n;j++)
{
if(p[i]==code[j].data)
for(t=0;code[j].bits[t]!='\0';t++)
if(code[j].bits[t]!='#')
coding[k++]=code[j].bits[t];
}
}
coding[k]='\0';
}
//******************************打印操作********************************//
void printcode(hufmtree *tree,codetype *code,int n,FILE *fp)
{
//打印字符的编码,结果存放在fp中
int i,j,t;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(code[j].data==tree[i].data)
{
fprintf(fp,"字符%c的编码:",tree[i].data);
for(t=0;code[j].bits[t]!='\0';t++)
if(code[j].bits[t]!='#')
fprintf(fp,"%c",code[j].bits[t]);
fprintf(fp,"\n");
}
}
for(j=0;j<n;j++)
{
if(code[j].data==' ')
{
fprintf(fp,"字符空格的编码:");
for(t=0;code[j].bits[t]!='\0';t++)
if(code[j].bits[t]!='#')
fprintf(fp,"%c",code[j].bits[t]);
fprintf(fp,"\n");
}
}
}
//**************************************************************************************
void inorder(hufmtree *tree,int k,FILE *fp) //问题函数
{ //函数功能是实现哈夫曼树的凹入法输出
//但是在进行嵌套循环时,tree指针好像变成了空指针 ,不知道为什么
//中序遍历并打印树,结果存放于fp中,k为根结点的下标 //求解惑
int i;
if(tree[k].rchild!=0){
DEPTH++;
inorder(tree,tree[k].rchild,fp);
DEPTH--;
}
for(i=1;i<=DEPTH;i++)fprintf(fp," ");
fprintf(fp,"%c\n",tree[k].data);
if(tree[k].lchild!=0){
DEPTH++;
inorder(tree,tree[k].lchild,fp);
DEPTH--;
}
if(tree[k].lchild&&tree[k].rchild==(-1))return;
return;
}
//***********************主函数**************************//
int main()
{
FILE *fp1,*fp2;
int n,m,j=0;
char a[50],b[50],coding[100],size[100],ch;
printf("输入字符长度:");
scanf("%d",&n);
m=2*n-2;
hufmtree *tree; codetype *code;
tree=(hufmtree*)malloc((2*n)*sizeof(hufmtree));
code=(codetype*)malloc((n+1)*sizeof(codetype));
printf("\n");
CreateHUFMT(tree,n,code);
printf("\n");
printf("请输入哈夫曼树文件存放地址:");
fp1=fopen("G:\\code\\hufmtree.txt","w+");
printf("\n");
printf("请输入字符编码文件存放地址:");
fp2=fopen("G:\\code\\hufmcode.txt","w+");
printf("\n");
inorder(tree,m,fp1);
printcode(tree,code,n,fp2);
fclose(fp1); fclose(fp2);
printf("\n");
printf("e:编码(Encode)\nd:译码(Decode)\nq:退出(Quit)\n");
printf("请输入操作:");
getchar();
ch=getchar();
printf("\n");
do
{
switch(ch)
{
case 'e':{Encode(code,coding,n);
printf("文本的哈夫曼编码是:%s\n",coding);
printf("编码完毕,请选择操作:\n");
printf("e:编码(Encode)\nd:译码(Decode)\nq:退出(Quit)\n");
break;
}
case 'd':{Decode(tree,size,n);
printf("文本的译码是:%s\n",size);
printf("译码完毕,请选择操作:\n");
printf("e:编码(Encode)\nd:译码(Decode)\nq:退出(Quit)\n");
break;
}
case 'q':exit(0);break;
default :exit(0);break;
}
ch=getchar();
}while(ch!='q');
}//************************编码与译码操作**********************************
void Decoding(HuffmanTree HT,hfmlist HL,char*size,int n)//这个函数是用来译码的
{int i,j,k;
char p[30];
printf("请输入需要译码的代码:");gets(p);//接受需要译码的字符串
i=2*n-1;
k=0;
for(j=0;p[j]!='\0';j++){
if(p[j]=='0'){ if(HT[i].lchild!=0)i=HT[i].lchild;
else{ size[k++]=HL[i].letter;
i=2*n-1;
j--;}
}
else{ if(HT[i].rchild!=0)i=HT[i].rchild;
else{ size[k++]=HL[i].letter;
i=2*n-1;
j--;}
}
}//for
if( p[j-1]=='0')size[k++]=HL[i].letter;
else size[k++]=HL[i].letter;
size[k]='\0';
}//decoding
void Encoding(HuffmanCode HC,hfmlist HL,char *coding,int n){
int i,j,t,k=0;
char p[100];
printf("请再次输入需要编码的文本:");
gets(p);
for(i=0;p[i]!='\0';i++){
if((p[i]>='a'&&p[i]<='z')||p[i]==' ')
for(j=1;j<=n;j++)
if(p[i]==HL[j].letter)
for(t=0;HC[j][t]!='\0';t++)
coding[k++]=HC[j][t];
}//for
coding[k]='\0';
}//encoding
//************************打印操作****************************
void Print(FILE *fp1,FILE *fp2){
//将文件fp1中的代码以紧凑格式显示在终端上,每行50个代码
//同时将此字符形式的编码文件写入文件fp2中
char c[200];
int i;
fgets(c,200,fp1);
for(i=0;c[i]=='0'||c[i]=='1';i++){
printf("%c",c[i]);
fprintf(fp2,"%c",c[i]);
if((i+1)/50*50==(i+1)){
printf("\n");
fprintf(fp2,"\n");
}
}//for
printf("\n");
}//Print
//********************************************************************!!!!!!!!!!!!!
void PreOrderTraverse(HuffmanTree HT,int k,FILE *fp){
//中序遍历并打印树,结果存放于fp中,k为根结点的下标
int i;
//这个函数跟我自己写的函数看上去没什么差异,但是却可以正常运行
if(HT[k].rchild!=0){ //百思不得其解
DEPTH++;
PreOrderTraverse(HT,HT[k].rchild,fp);
DEPTH--;
}
for(i=1;i<=DEPTH;i++)fprintf(fp," ");
fprintf(fp,"%d\n",HT[k].weight);
if(HT[k].lchild!=0){
DEPTH++;
PreOrderTraverse(HT,HT[k].lchild,fp);
DEPTH--;
}
if(HT[k].lchild==0&&HT[k].rchild==0)return;
return;
} //PreOrderTraverse
//********************************************************************!!!!!!!!!!!!!!!!
void TreePrinting(HuffmanTree HT,int n,FILE *fp){
//打印树HT,结果存于文件fp中,n为树的叶子结点数
int i,k;
for(i=1;i<=2*n;i++)if(HT[i].parent==0){k=i;break;}//寻找根结点
PreOrderTraverse(HT,k,fp);
return;
}//TreePrinting
//**************************主函数*********************************
int main()
{
FILE *fp1,*fp2,*fp3,*fp4,*fp5;
HuffmanTree HT;
HuffmanCode HC;
hfmlist HL;
unsigned int i,n;
char *b,c[100],cha,ch;
b=(char *)malloc(100*sizeof(char));
printf("请选择操作:\n");
printf("i:初始化(Initialization)\ne:编码(Encoding)\nd:译码(Decoding)\n");
printf("p:印代码文件(Print)\nt:印哈夫曼树(Tree printing)\nq:退出(Quit)\n");b=(char *)malloc(100*sizeof(char));
HL=(hfmlist)malloc(30*sizeof(hfm));//存储字符与权值,线性表长30
printf("\n");
printf("选择操作(i,e,d,p,t,q):");
ch=getchar();
getchar();
printf("\n");
do{
switch(ch){
case 'i':printf("正在进行初始化……\n");
printf("输入字符长度:");
scanf("%d",&n);
getchar();
printf("\n");
HC=(HuffmanCode)malloc((n+1)*sizeof(char));
HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));
for(i=1;i<=n;i++){
printf("请输入第%d个字符及权值(格式:字符 权值):",i);
scanf("%c %d",&(HL+i)->letter,&(HL+i)->wt);
getchar();
}//for
if((fp5=fopen("G:\\code\\hufmtree.txt","w+"))==NULL){
printf("cannot open file!\n");
exit(0);
}//if
for(i=1;i<=n;i++){
fprintf(fp5,"第%d个字符及权值:\t\t\t",i);
fprintf(fp5,"%c %d\n",(HL+i)->letter,(HL+i)->wt);
}//for
fclose(fp5);
HuffmanCoding(HT,HC,HL,n);
printf("\n已经将Huffman树存入文件hfmTree.txt中\n\n");
printf("初始化完毕,请选择操作:\n");
printf("i:重新初始化(Initialization)\ne:编码(Encoding)\nd:译码(Decoding)\n");
printf("p:印代码文件(Print)\nt:印哈夫曼树(Tree printing)\nq:退出(Quit)\n\n");
break;
case 'e':
printf("请输入编码,以#结尾:");
if((fp2=fopen("ToBeTran.txt","w"))==NULL){
printf("cannot open file\n");exit(0);
}//if
cha=getchar();
while(cha!='#')
{
fputc(cha,fp2);
cha=getchar();
}//while
getchar();
fclose(fp2);
printf("已经把编码存入文件ToBeTran.txt中\n\n");
Encoding(HC,HL,b,n);
printf("文本的哈夫曼编码是:");
printf("%s\n",b);
printf("下面进行保存:");
save(b);
printf("编码完毕,请选择操作:\n");
printf("i:重新初始化(Initialization)\ne:编码(Encoding)\nd:译码(Decoding)\n");
printf("p:印代码文件(Print)\nt:印哈夫曼树(Tree printing)\nq:退出(Quit)\n");
break;
case 'd':
Decoding(HT,HL,c,n);
printf("输入要译码的编码:");
printf("正在进行译码……\n");
printf("%s\n",c);
save(c);
printf("已经将结果存入文件%s中\n",a);
printf("译码完毕,请选择操作:\n");
printf("i:重新初始化(Initialization)\ne:编码(Encoding)\nd:译码(Decoding)\n");
printf("p:印代码文件(Print)\nt:印哈夫曼树(Tree printing)\nq:退出(Quit)\n");
break;
case 'p':
for(i=1;i<=n;i++)
printf("字符:%c\t\t\t译码:%s\n",HL[i].letter,HC[i]);
if((fp1=fopen("CodePrin.txt","w"))==NULL){
printf("cannot open the file!\n");
exit(0);
}//if
if((fp4=fopen("CodeFile.txt","r"))==NULL){
printf("cannot open the file!\n");
exit(0);
}//if
Print(fp4,fp1);
printf("该代码文件已经存在并命名为CodePrin.txt\n");
fclose(fp4);
fclose(fp1);
break;
case 't':printf("打印树存在于文件TreePrin中\n");
if((fp3=fopen("G:\\code\\hufmtree.txt","w+"))==NULL)
{printf("cannot open file\n");exit(0);}
TreePrinting(HT,n,fp3);
fclose(fp3);
break;
case 'q':exit(0);break;
default :exit(0);break;
}//switch
printf("\n请选择操作(i,e,d,p,t,q):");
ch=getchar();
getchar();
}while(ch!='q');//do
}
接上面的#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct {
char letter;
int wt;
}hfm,*hfmlist;
//*************************全局变量************************************
unsigned int s1,s2,n;
char choose;
int DEPTH=0;
char a[20];
//***************Huffman树和Huffman编码的存储表示**********************
typedef struct{
unsigned int weight;
unsigned int code;
unsigned int parent,lchild,rchild;
}HTNode, *HuffmanTree; //动态分配数组存储Huffman树
typedef char * *HuffmanCode; //动态分配数组存储Huffman编码表
//***************************初始化Huffman树***************************
void select(HuffmanTree HT,int l){
int a,b,c,j;
s1=s2=1;
a=b=1000;
for(j=1;j<=l;j++){
if(HT[j].code==0){
c=HT[j].weight;
if(c<a){b=a;a=c;s2=s1;s1=j;}
else if(c<b){b=c;s2=j;}
}//if
}//for
HT[s1].code=HT[s2].code=1;
}//select
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC, hfmlist HL,unsigned int n){
//w存放n个权值(均>0),构造Huffman树HT,并求出n个字符的Huffman编码HC.
unsigned int i,f,start,c,m;
char*cd;
if (n<=1) return;
m =2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=m;++i){HT[i].weight=HT[i].parent=HT[i].lchild=HT[i].rchild=HT[i].code=0;}
for(i=1;i<=n;++i)HT[i].weight=HL[i].wt;
for (i=n+1;i<=m;++i){
select(HT,i-1);
HT[s1].parent=i;HT[s2].parent=i;
HT[i].lchild=s1;HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i){
start=n-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if (HT[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],cd+start);
}
free(cd);
}
//*************************文件操作*****************************
void save (char *p){
FILE *fp;
int i;
printf("input the name:");
if((fp=fopen(gets(a),"w+"))==NULL){
printf("cannot open the file!\n");
exit(0);}//if
for(i=0;p[i]!='\0';i++){
if(fwrite(p+i,sizeof(char),1,fp)!=1){//fwrite函数写数据块
printf("File write error!\n");exit(0);}//if
}//for
fclose(fp);
}//save
这个是我在网上找到的类似的代码,但是这个代码可以正常运行,不知道我跟这个的区别在哪里