哈夫曼编解码 完整c程序代码
c语言实现哈夫曼算法
![c语言实现哈夫曼算法](https://img.taocdn.com/s3/m/c947f0fcfc0a79563c1ec5da50e2524de518d09a.png)
c语言实现哈夫曼算法以下是C语言实现哈夫曼算法的示例代码:```cinclude <>include <>include <>// 定义哈夫曼树节点结构体typedef struct HuffmanNode {char data; // 节点存储的数据int freq; // 节点出现的频率struct HuffmanNode left, right; // 左右子树指针} HuffmanNode;// 定义创建哈夫曼树函数HuffmanNode createNode(char data, int freq) { HuffmanNode node =(HuffmanNode)malloc(sizeof(HuffmanNode));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 定义比较函数,用于按照频率从小到大排序int compare(const void a, const void b) {return ((HuffmanNode)b)->freq - ((HuffmanNode)a)->freq; }// 定义构建哈夫曼树函数HuffmanNode buildHuffmanTree(char data[], int freq[], int size) { if (size == 1) {return createNode(data[0], freq[0]);} else {HuffmanNode nodes[size]; // 存储所有节点指针的数组for (int i = 0; i < size; i++) {nodes[i] = createNode(data[i], freq[i]);}qsort(nodes, size, sizeof(HuffmanNode), compare); // 按频率从小到大排序return mergeNodes(nodes, size); // 合并两个最小的节点,直到只剩下一个节点}}// 定义合并两个最小节点函数HuffmanNode mergeNodes(HuffmanNode nodes[], int size) {if (size == 0) return NULL; // 空节点返回NULL指针if (size == 1) return nodes[0]; // 只剩下一个节点直接返回该节点指针 HuffmanNode root = createNode('$', nodes[0]->freq + nodes[1]->freq); // 创建根节点,频率为左右子树频率之和root->left = mergeNodes(nodes+1, size-1); // 递归合并剩余节点,左子树指向左子树数组中除第一个节点外的所有节点指针,右子树指向右子树数组中除最后一个节点外的所有节点指针return root; // 返回根节点指针}```。
哈夫曼编码算法实现完整版
![哈夫曼编码算法实现完整版](https://img.taocdn.com/s3/m/291384d0ba0d4a7303763a21.png)
实验三树的应用一.实验题目:树的应用——哈夫曼编码二.实验内容:利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。
根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。
要求:从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码。
三、程序源代码:#include <iostream.h>#include <fstream.h>#include <string.h>#include <stdlib.h>typedef struct{char data;int weight;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char * * HuffmanCode;void Select(HuffmanTree &HT,int n,int m){HuffmanTree p=HT;int tmp;for(int j=n+1;j<=m;j++){int tag1,tag2,s1,s2;tag1=tag2=32767;for(int x=1;x<=j-1;x++){ if(p[x].parent==0&&p[x].weight<tag1){ tag1=p[x].weight;s1=x;}}for(int y=1;y<=j-1;y++){ if(p[y].parent==0&&y!=s1&&p[y].weight<tag2){ tag2=p[y].weight;s2=y;}}if(s1>s2) //将选出的两个节点中的序号较小的始终赋给s1{ tmp=s1; s1=s2; s2=tmp;}p[s1].parent=j;p[s2].parent=j;p[j].lchild=s1;p[j].rchild=s2;p[j].weight=p[s1].weight+p[s2].weight;}}void HuffmanCoding(HuffmanTree &HT,int n,char *w1,int*w2){int m=2*n-1;if(n<=1) return;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));HuffmanTree p=HT;for(int i=1;i<=n;i++){ p[i].data=w1[i-1];p[i].weight=w2[i];p[i].parent=p[i].lchild=p[i].rchild=0;}for(;i<=m;i++){ p[i].weight=p[i].parent=p[i].lchild=p[i].rchild=0; }Select(HT,n,m);ofstream outfile; //生成hfmTree文件outfile.open("hfmTree.txt",ios::out);for (i=1;i<=m;i++){outfile<<HT[i].weight<<"\t"<<HT[i].parent<<"\t"<<HT[i].lchild<<"\t"<<HT[i].rchild<<"\t"<<endl;}outfile.close();cout<<"初始化结果已保存在hfmTree文件中\n";}void ToBeTree() //将正文写入文件ToBeTree中{ofstream outfile;outfile.open("ToBeTree.txt",ios::out);outfile<<"THIS PROGRAM IS MYFA VORITE";outfile.close();}void Encoding(HuffmanTree &HT,int n) //编码{HuffmanCode HC;HC=(HuffmanCode)malloc((n+1)*sizeof(char *));char *cd;cd=(char *)malloc(n*sizeof(char));cd[n-1]='\0';for(int k=1;k<=n;k++){ int start=n-1;for(int c=k,f=HT[k].parent;f!=0;c=f,f=HT[f].parent){ if(HT[f].lchild==c) cd[--start]='0';else cd[--start]='1';}HC[k]=(char *)malloc((n-start)*sizeof(char));strcpy(HC[k],&cd[start]);}cout<<"输出哈夫曼编码:"<<endl;for(int h=1;h<=n;h++) //输出编码{ cout<<HT[h].data<<":";cout<<HC[h];cout<<" ";if (h%8==0) cout<<endl;}cout<<endl<<"输出正文编码:"<<endl;ToBeTree();//读取TOBETREE文件里的正文,并进行编码fstream infile;infile.open("ToBeTree.txt",ios::in);char s[80];while(!infile.eof()){infile.getline(s,sizeof(s));}infile.close();fstream outfile;outfile.open("CodeFile.txt",ios::out);int count=0;for (h=0;s[h]!='\0';h++){ for(k=1;k<=n;k++)if (s[h]==HT[k].data){ cout<<HC[k];cout<<" ";count++;outfile<<HC[k];break;}if (count%9==0) cout<<endl; //每输出7个换行}outfile.close();cout<<"\n编码结果已保存在文件CodeFile中.";cout<<endl;}void Decoding(HuffmanTree &HT,int n) //译码{int f=2*n-1;fstream infile;infile.open("CodeFile.txt",ios::in);char s[1000];while(!infile.eof()){infile.getline(s,sizeof(s));}infile.close();int i=0;int j=0;fstream outfile;outfile.open("TextFile.txt",ios::out);while(s[i]!='\0'){ f=2*n-1;while(HT[f].lchild!=0)//以f对应的节点的左孩子的值==0作为结束{if (s[j]=='0') f=HT[f].lchild;else f=HT[f].rchild;j++;}i=j;cout<<HT[f].data;outfile<<HT[f].data;}outfile.close();cout<<"\n译码结果已保存在文件TextFile中.";cout<<endl;}void Print() //印代码文件{ int count=0;fstream infile;infile.open("CodeFile.txt",ios::in);char s[1000];while(!infile.eof()){infile.getline(s,sizeof(s));for(int i=0;s[i]!='\0';i++){ cout<<s[i];count++;if (count%50==0) cout<<endl; //在终端上每行显示50个代码}}infile.close();cout<<endl;}char menu() //菜单函数{ cout<<"功能菜单如下:"<<endl;cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl;cout<<" I:初始化(Initialization) "<<endl;cout<<" E:编码(Encoding) "<<endl;cout<<" D:译码(Decoding) "<<endl;cout<<" P:印代码文件(Print) "<<endl;cout<<" Q:退出(Exit) "<<endl;cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl;cout<<"请输入功能字符:";char ch;cin>>ch;return ch;}void main(){ int n;int Array[100];char cArray[100];HuffmanTree HT;cout<<"输入n个字符:";cin.getline(cArray,100);n=strlen(cArray);cout<<"一共"<<n<<"个字符.\n";cout<<"依次输入各个字符的权值:"<<endl;for (int i=1;i<=n;i++) cin>>Array[i];int tag;char x=menu();while(1){ switch (x){case 'I':HuffmanCoding(HT,n,cArray,Array);break;case 'E':Encoding(HT,n);break;case 'D':Decoding(HT,n);break;case 'P':Print();break;case 'Q':tag=0;cout<<"结束"<<endl;break;default:cout<<"你输入错误!"<<endl;}if(tag==0) break;cout<<"y(继续) or n(退出)"<<endl;char ch;cin>>ch;if (ch=='y'){ cout<<"请输入功能字符:";char c;cin>>c;x=c;}else exit(1);}}测试数据:用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的译码和编码:"THIS PROGRAM IS MY FAVORITE".字符空格 A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1四.测试结果:如图一所示五.实验体会通过本次实验,尤其在自己对程序的调试过程中,感觉对树的存储结构,终结状态,还有编码,译码的过程都有了比较清晰的认识。
C语言哈夫曼编码代码
![C语言哈夫曼编码代码](https://img.taocdn.com/s3/m/187a785d0722192e4536f6ed.png)
#include<string.h>#include<stdlib.h>#include<stdio.h>int m,s1,s2;typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表void Select(HuffmanTree HT,int n) {int i,j;for(i = 1;i <= n;i++)if(!HT[i].parent){s1 = i;break;}for(j = i+1;j <= n;j++)if(!HT[j].parent){s2 = j;break;}for(i = 1;i <= n;i++)if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i; for(j = 1;j <= n;j++)if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j; }void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {// 算法6.13// w存放n个字符的权值(均>0),构造哈夫曼树HT,// 并求出n个字符的哈夫曼编码HCint i, j;char *cd;int p;int cdlen;if (n<=1) return;m = 2 * n - 1;HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用for (i=1; i<=n; i++) { //初始化HT[i].weight=w[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for (i=n+1; i<=m; i++) { //初始化HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}puts("\n哈夫曼树的构造过程如下所示:");printf("HT初态:\n 结点weight parent lchild rchild");for (i=1; i<=m; i++)printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);printf(" 按任意键,继续...");getchar();for (i=n+1; i<=m; i++) { // 建哈夫曼树// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,// 其序号分别为s1和s2。
哈夫曼编码译码C语言编写
![哈夫曼编码译码C语言编写](https://img.taocdn.com/s3/m/a0f5451efad6195f312ba600.png)
哈夫曼编码译码C语言编写10[ 标签:哈夫曼,编码,译码 ]如上题 C语言编个程序懂的帮搞个能运行的程序来#11别到网上找那些我找过了没用的蝶风待夕魂回答:2 人气:19 解决时间:2009-05-14 18:44满意答案好评率:100%#include<stdio.h>#include<stdlib.h>#include<string.h>typedef char ElemType;typedef struct{ElemType elem;unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char** HuffmanCode;typedef int Status;typedef struct {char elem;unsigned int weight;}Weight; // save the information of the symbolizes;void HuffmanCoding(HuffmanTree *,HuffmanCode *,Weight *,int);void Select(HuffmanTree,int,int *,int *);void OutputHuffmanCode(HuffmanTree,HuffmanCode,int);Status main(void){HuffmanTree HT;HuffmanCode HC;Weight *w;char c;int i,n;int wei;printf("input the tatol number of the Huffman Tree:" );scanf("%d",&n);w=(Weight *)malloc(n*sizeof(Weight));for(i=0;i<n;i++){printf("input the element & its weight:");scanf("%1s%d",&c,&wei);w[i].elem=c;w[i].weight=wei;}HuffmanCoding(&HT,&HC,w,n);OutputHuffmanCode(HT,HC,n);return 1;}回答人的补充 2009-05-08 00:07接上面的。
哈夫曼信源编码c语言程序代码
![哈夫曼信源编码c语言程序代码](https://img.taocdn.com/s3/m/04c5b8f5bb0d4a7302768e9951e79b896802687c.png)
哈夫曼信源编码c语言程序代码哈夫曼编码的C语言实现编码原理程序步骤的分析:哈夫曼码是用概率匹配方法进行信源编码。
编程时应该注意:1,概率大的符号对应于短码,概率小的对应于长码,充分利用短码;2缩减信源的最后二个码字,总是最后一位不同,保证了哈夫曼码是即时码。
程序步骤:(见信息论课本p88页内容)(l)将信号源的符号按照出现概率递减的顺序排列。
(2)将两个概率最小的字母分别配以0和1两个码元,并将这两个概率相加作为一个新字母的概率(3)重排后的两个概率最小符号重复步骤(2)过程。
(4)不断继续上述过程,直到最后两个符号配以0和1为止(5)从最后一级开始向前返回各个信源符号所对应的码元序列,及相应的码字。
根据以上规则编码可知:哈夫曼编码实际上构造了一个码树,码树从最上层的端点开始构造,到树根结束,最后得到一个横放的码树,所以编出的码是即时码。
哈夫曼编码概率大的符号对应于短码,概率小的符号对应于长码,使平均码长最小。
每次对概率最小的两个符号求概率之和形成缩减信源时,构造出两个树枝,由于给两个树枝赋码元时是任意的,因此编出的码字不惟一。
程序源代码如下;#include stdio.h#include malloc.h #include conio.h #include string.h #include stdlib.h #define HuffmanTree HF #define HuffmanCode HMC typedef struct {unsigned int weight; unsigned int parent,lchild,rchild; } HTNode,*HF; typedef char **HMC; typedef struct { unsigned int s1; unsigned int s2; } MinCode; void Error(char *message); HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n); MinCode Select(HF HT,unsigned int n); void Error(char *message) { fprintf(stderr,“Error:%s\n",message); exit(1); } HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n) { unsigned int i,s1=0,s2=0; HF p; char *cd; unsigned int f,c,start,m; MinCode min; if(n=1) Error("Code too small!"); m=2*n-1;HT=(HF)malloc((m+1)*sizeof(HTNode)); for(p=HT,i=0;ii++,p++,w++) { p-weight=*w; p-parent=0; p-lchild=0; p-rchild=0; } for(;ii++,p++) { p-weight=0; p-parent=0; p-lchild=0; p-rchild=0; } for(i=n+1;ii++){ min=Select(HT,i-1); s1=min.s1; s2=min.s2;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; } printf("HT List:\n");printf("Number\t\tweight\t\tparent\t\tlchild\t\trchild\n"); for(i=1;ii++) printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);HC=(HMC)malloc((n+1)*sizeof(char *)); cd=(char *)malloc(n*sizeof(char *)); cd[n-1]='\0'; for(i=1;ii++) { 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); return HC; } void main() {MinCode Select(HF HT,unsigned int n); HF HT=NULL; HuffmanCode HC=NULL; unsigned int *w=NULL; unsigned int i,n; printf("请输入节点个数n:"); scanf("%d", w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *));w=0; printf("请输入权重:\n"); for(i=1;ii++) { printf("w[%d]=",i);scanf("%d",w[i]); } HC=HuffmanCoding(HT,HC,w,n); printf("HMC:\n");printf("Number\t\tWeight\t\tCode\n"); for(i=1;ii++)printf("%d\t\t%d\t\t%s\n",i,w[i],HC[i]); } MinCode Select(HF HT,unsigned int n) { unsigned int min,secmin; unsigned int temp; unsigned int i,s1,s2,tempi; MinCode code;s1=1;s2=1; for(i=1;ii++) if(HT[i].parent==0) { min=HT[i].weight; s1=i; break; } tempi=i++; for(;ii++) if(HT[i].weightminHT[i].parent==0){ min=HT[i].weight; s1=i; } for(i=tempi;ii++) if(HT[i].parent==0i!=s1){ secmin=HT[i].weight; s2=i; break; } for(i=1;ii++)if(HT[i].weightsecmini!=s1HT[i].parent==0) { secmin=HT[i].weight; s2=i; } if(s1s2){ temp=s1; s1=s2; s2=temp; } code.s1=s1; code.s2=s2; return code; } 运行结果如下:请输入节点个数n:5请输入权重:w=2 w=3 w=1 w=1 w=3 Number Weight Code 1 2 00 2 3 10 3 1 010 4 1 011 5 3 11 Press any key to continue编程感想及总结:正如事物均具有两面性,哈夫曼编码也具有优点和缺点,比如哈夫曼编码可以取得较好的荣誉压缩效果,使得输出码元概率均匀化。
哈夫曼编解码 完整c程序代码
![哈夫曼编解码 完整c程序代码](https://img.taocdn.com/s3/m/077a3112f524ccbff0218413.png)
哈夫曼编解码完整c程序代码Huffman 编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据进行预先编码,在接收端进行解码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/解码系统。
2)要求:一个完整的huffman编解码系统应该具有以下功能:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立Huffman 树,并将它存入hfmTree 中。
编码(Encoding)。
利用已经建好的Huffman树(如果不在内存,则应从文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
解码(Decoding)。
利用已经建立好的Huffman树将文件CodeFile中的代码进行解码,结果存入TextFile中。
打印代码文件(Print)。
将文件CodeFile以紧凑的格式显示在终端上,每行50 个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
打印Huffman树(Tree Printing)。
将已经在内存中的Huffman树以直观的形式(树或者凹入的形式)显示在终端上,同时将此字符形式的Huffman 树写入文件TreePrint中。
3) 测试数据: 用下表给出的字符集和频度的实际统计数据建立Huffman树,并对以下报文进行编码和译码:“THIS PROGRAM IS MY FAVORITE”。
字符 A B C D E F G H I J K L M 频度1866413223210321154757153220 字符 N O P Q R S T U V W X Y Z 频度5763151485180238181161 完整代码如下:#include<stdio、h>#include<iostream>#include<string>#define N100int*w;char *c,stack[N],code[N][N];int s1,s2;typedef struct HuffmanTree{int weight;int parent;int lchild;int rchild;}HuffmanTree,*Huff;void menu(void); voidSelect(struct HuffmanTree HT[],int i); voidHuffmanTree(Huff &HT,int *w,int n);void visite(HuffHT,int i,int flag,int rear);void translatef(char*scource,char *save,int n);bool uncodef(FILE *fp1,FILE*fp2,Huff HT,int n);int inputHuff();void screanio(int n);void fileio(int n);int initHuff();void Print_tree(int n,Huff HT);void Convert_tree(Huff HT,unsigned charT[100][100],int tt[100][100],int s,int *i,int j);void decoding(int n);void coding(int n);void main(){intn=0;menu();Huff HT;char state;do{std::cout<<"input:\n";std::cin>>state;fflush(stdin); //读取状态switch(state){ caseI:n=inputHuff();HuffmanTree(HT,w,n);st d::cout<<"\nHuffmanTree 初始化完毕\n";break;caseC:coding(n);break; caseD:decoding(n);break;caseP:Print_tree(n,HT);break;caseQ:break;}}while(state!=Q);}void menu()//显示菜单函数{std::cout<<"===========HuffmanCoding===========\n"; std::cout<<"input \t\t do\n";std::cout<<"I\t\tInit_HUffTree\n"; //初始化huffmantreestd::cout<<"C \t\tCoding\n"; //对ToBeTran、txt文件中的字符进行编码到CodeFile、txt中std::cout<<"D \t\tUnCoding\n"; //对CodeFile、txt中的01序列进行解码到TextFile、txtstd::cout<<"P \t\tPrintTree\n"; //打印哈夫曼树std::cout<<"Q \t\tquit\n";std::cout<<"请初始化哈夫曼树再执行后面的操作\n";}int inputHuff()//输入各个字母及其权值{int i=1,n=0;int ww[28];char cc[28];while(1){std::cout<<"input the letter(input # to stop):";cc[i]=std::cin、get();fflush(stdin);if(cc[i]==#)break;std::cout<<"inputtheweight:";std::cin>>ww[i];fflush(stdin);n++;i++;}w=(int *)malloc(sizeof(int)*(n+1));c=(char*)malloc(sizeof(char)*(n+1));for(i=0;i<n+1;i++){w[i]=ww[i ];c[i]=cc[i];}return n;}void HuffmanTree(Huff &HT,int*w,int n)//初始化哈夫曼树{int m,i;m=n*2-1;HT=(struct HuffmanTree *)malloc(sizeof(structHuffmanTree)*(m+1));HT[0]、lchild=0;HT[0]、parent=0;HT[0]、rchild=0;HT[0]、weight=0;for(i=1;i<m;i++){HT[i]、weight=i<=n?w[i]:0;HT[i]、lchild=HT[i]、rchild=HT[i]、parent=0;}for(i=n+1;i<=m;i++){ Select(HT,i);HT[i]、lchild=s1;HT[i]、rchild=s2;HT[i]、weight=HT[s1]、weight+HT[s2]、weight;HT[s1]、parent=HT[s2]、parent=i;}}void Select(struct HuffmanTree HT[],int i) //在HT[1、、i-1]中选择parent为0且weight为最小的两个结点{ int j;for(j=1;j<i;j++){if(HT[j]、parent==0){s1=j;s2=j;goto flag;}}flag:for(j=s1+1;j<i;j++){if(HT[j]、parent==0){if(HT[s1]、weight >=HT[j]、weight){s2=s1;s1=j;}if(HT[s2]、weight>HT[j]、weight&&j!=s1)s2=j;if(s1==s2)s2=j;}}}void Print_tree(int n,Huff HT)//以凹入法的形式打印树{ unsigned char T[100][100];int tt[100][100]; int i,j,m=0; FILE *fp;Convert_tree(HT,T,tt,0,&m,2*n-1); //将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中if((fp=fopen("treeprint、txt","wb+"))==NULL)printf("Open file treeprint、txt error!\n");printf("\n以凹凸表形式打印已建好的赫夫曼树:\n");for(i=1;i<=2*n-1;i++){ for (j=0;T[i][j]!=0;j++){ if(T[i][j]== ){printf(" ");fputc(T[i][j],fp);} else{printf("%d",tt[i][j]);fprintf(fp,"%d\n\n\n",tt[i][j]);} } printf("\n"); } fclose(fp); printf("\n此字符形式的哈夫曼树已写入文件treeprint、txt中、\n\n"); printf("\n文件treeprint、txt的打开方式要为写字板,若打开方式为记事本,则无法显示凹凸表的形式\n"); } void Convert_tree(HuffHT,unsigned char T[100][100],int tt[100][100],int s,int*i,int j)//将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中{ int k,l; l=++(*i); for(k=0;k<s;k++)T[l][k]= ; T[l][k]=#; tt[l][k]=HT[j]、weight;if(HT[j]、lchild)Convert_tree(HT,T,tt,s+1,i,HT[j]、lchild); if(HT[j]、rchild)Convert_tree(HT,T,tt,s+1,i,HT[j]、rchild);T[l][++k]=\0; } void coding(int n)//对文件ToBeTran、txt编码到CodeFile、txt{ FILE*fp1;Huff HT;HuffmanTree(HT,w,n);visite(HT,2*n-1,2,0);fflush(stdin);translatef("ToBeTran、txt","CodeFile、txt",n);fp1=fopen("CodeFile、txt","r");printf("\n编码已写入文件treeprint、txt中、\n");fclose(fp1);}void decoding(int n)//对CodeFile、txt中的01序列进行解码到TextFile、txt{FILE *fp1,*fp2;HuffHT;HuffmanTree(HT,w,n);fp1=fopen("CodeFile、txt","r");fp2=fopen("TextFile、txt","w");while(uncodef(fp1,fp2,HT,2*n-1));printf("\n");printf("\n解码已写入文件TextFile、txt 中、\n");fclose(fp1);fclose(fp2);}void visite(Huff HT,int i,int flag,int rear)//通过递归调用visite()函数,得到各个字母的编码,存储于全局变量code[][]中{intj=0,k=0;if(flag==0){ stack[rear]=0;rear++;}elseif(flag==1){stack[rear]=1;rear++;}if(HT[i]、lchild==0){for(j=0;j<rear;j++){code[i][j]=stack[j];}code[ i][j]=#;rear--;return;}visite(HT,HT[i]、lchild,0,rear);visite(HT,HT[i]、rchild,1,rear);k=rear;for(j=0;j<k;j++){code[i][j]=stack[j ];}code[i][j]=#;rear--;return;}void translatef(char*scource,char *save,int n)//读取文件中的字母序列,并根据code[][]将其转换成01序列输出{FILE *fp1,*fp2;char p= ;int i=0,j=0,k=0;fp1=fopen(scource,"r");fp2=fopen(save,"w");p= fgetc(fp1);printf("\n得到的编码为:\n");while(p!=EOF){for(i=0;i<=n;i++){if(c[i]==p){for(j =0;j<N&&code[i][j]!=#;j++){fputc(code[i][j],fp2);putchar( code[i][j]);k++;if(k>=50){k=0;putchar(\n);}}}}p=fgetc(fp1 );}fclose(fp1);fclose(fp2);}bool uncodef(FILE *fp1,FILE *fp2,Huff HT,int n)//通过对树的访问,把文件中01序列转换成一个字母输出。
C++实现哈夫曼编码完整代码
![C++实现哈夫曼编码完整代码](https://img.taocdn.com/s3/m/1c1540d849649b6648d7479c.png)
C++实现哈夫曼编码完整代码#include <iostream>#include <queue>#include <vector>#include <map>#include <string>using namespace std;class Node {public:char c; //表示字符int frequency; //表示该字符出现的次数或频率Node *left;Node *right;Node(char _c, int f, Node *l = NULL, Node *r = NULL):c(_c), frequency(f), left(l), right(r) { }bool operator<(const Node &node) const { //重载<运算法以至于在加入优先队列的时候决定如何处理结点位置return frequency > node.frequency;}};void initNode(priority_queue<Node> &q, int nodeNum) {char c;int frequency;for (int i = 0; i < nodeNum; i++) {cout << "输入字符和结点出现的次数: ";cin >> c >> frequency;Node node(c, frequency);q.push(node);}}void showNode(priority_queue<Node> q) {while (!q.empty()) {Node node = q.top(); q.pop();cout << node.c << ", " << node.frequency << endl;}}//构造哈夫曼树void huffmanTree(priority_queue<Node> &q) {while (q.size() != 1) {Node *left = new Node(q.top()); q.pop();Node *right = new Node(q.top()); q.pop();Node node('R', left->frequency + right->frequency, left, right);q.push(node);}}// 打印哈夫曼编码void huffmanCode(Node *root, string &prefix, map<char, string> &result) { string m_prefix = prefix;if (root->left == NULL)return;//处理左子树prefix += "0";//如果是叶子结点则输出,否则递归打印左子树if (root->left->left == NULL)result[root->left->c] = prefix;//cout << root->left->c << ": " << prefix << endl;elsehuffmanCode(root->left, prefix, result);//还原原来的路径,回溯prefix = m_prefix;//处理右子树prefix += "1";//如果是叶子结点,则输出, 否则递归打印右子树if (root->right->right == NULL)result[root->right->c] = prefix;//cout << root->right->c << ": " << prefix << endl;elsehuffmanCode(root->right, prefix, result);}void testResult(map<char, string> result) {//迭代map容器map<char, string>::const_iterator it = result.begin(); while (it != result.end()) {cout << it->first << ": " << it->second << endl;++it;}}int main() {priority_queue<Node> q;int nodeNum;//初始化字符信息cout << "请输入结点个数: ";cin >> nodeNum;initNode(q, nodeNum);//showNode(q);//构造哈夫曼树huffmanTree(q);//构造哈夫曼编码Node root = q.top();string prefix = "";map<char, string> result;huffmanCode(&root, prefix, result);//检验结果是否正确testResult(result);return 0;}。
哈夫曼编码-数据结构-C程序
![哈夫曼编码-数据结构-C程序](https://img.taocdn.com/s3/m/06c254b67e21af45b207a861.png)
数据结构课程设计一、目的《数据结构》是一门实践性较强的软件基础课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。
本课程设计的目的就是要达到理论与实际应用相结合,使同学们能够根据数据对象的特性,学会数据组织的方法,能把现实世界中的实际问题在计算机内部表示出来,并培养基本的、良好的程序设计技能。
二、要求通过这次设计,要求在数据结构析逻辑特性和物理表示,数据结构的选择的应用、算法的设计及其实现等方面中深对课程基本内容的理解。
同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。
三、内容2.哈夫曼编码/译码器【问题描述】设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
【基本要求】(1)初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;(2)编码:利用建好的哈夫曼树生成哈夫曼编码;(3)输出编码;(4)设字符集及频度如下表:字符空格A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1【选做内容】(1)译码功能;(2)显示哈夫曼树;(3)界面设计的优化。
哈夫曼编写编译码一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,这要求在发送端通过一个编码系统对待传输预先编码,在接收端将传来的数据进行译码。
对于双工通道,每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼码的编/译码系统。
二、概要设计1.哈夫曼树的定义:在一棵二叉树中,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。
2.哈夫曼树的构造:假设有N个权值,则构造出的哈夫曼树有N个叶子结点。
N个权值分别设为W1,W2,……….Wn,则哈夫曼树的构造规则为:(1)将W1,W2,……….Wn看成有N棵树的森林;(2)在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左,右子树,且新树的根结点为其左,右子树结点权值之和;(3)从森林中删除选取取的两面三刀棵树,并将新树加入森林;(4)重复(2)(3)步,直到森林中只剩一棵树为止,该树即为我们所求得的哈夫曼树。
用c语言实现哈夫曼编码
![用c语言实现哈夫曼编码](https://img.taocdn.com/s3/m/daf3900468eae009581b6bd97f1922791788be12.png)
用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。
以下是一个简单的使用C语言实现哈夫曼编码的例子。
这个例子只实现了编码过程,没有实现解码过程。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。
哈夫曼树编码c语言
![哈夫曼树编码c语言](https://img.taocdn.com/s3/m/6654649129ea81c758f5f61fb7360b4c2f3f2a44.png)
以下是C语言实现哈夫曼树编码的示例代码:```c#include <stdio.h>#include <stdlib.h>// 定义结构体表示节点struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;};// 创建新节点struct TreeNode* newNode(int val) {struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));node->val = val;node->left = NULL;node->right = NULL;return node;}// 计算权值和int calculateWeightSum(struct TreeNode* root) {if (root == NULL) {return 0;}return root->val + calculateWeightSum(root->left) + calculateWeightSum(root->right);}// 构建哈夫曼树struct TreeNode* buildHuffmanTree(int** freq, int size) {// 创建频率数组int arr[size];for (int i = 0; i < size; i++) {arr[i] = freq[i][0];}// 构建哈夫曼树struct TreeNode* root = NULL;int index = 0;while (index < size) {int min1 = INT_MAX, min2 = INT_MAX;int min1Index = -1, min2Index = -1;for (int i = 0; i < size; i++) {if (arr[i] < min1 && arr[i] != 0) {min1 = arr[i];min1Index = i;}if (arr[i] < min2 && arr[i] != 0) {min2 = arr[i];min2Index = i;}}// 创建新节点作为左右子树,并加入频率数组中arr[min1Index] = 0;arr[min2Index] = 0;struct TreeNode* left = newNode(min1);struct TreeNode* right = newNode(min2);left->left = right;right->right = left;// 将左右子树作为新的根节点,并更新频率数组和根节点指针if (root == NULL) {root = left;} else {struct TreeNode* parent = root;while (parent->left != NULL) {parent = parent->left;}parent->left = left;left->parent = parent;while (parent->right != NULL) {parent = parent->right;}parent->right = right;right->parent = parent;}index += 2; // 跳过左右子树,继续寻找下一对最小的节点构建子树,直到遍历完所有节点为止。
信息论实验哈夫曼编码c语言
![信息论实验哈夫曼编码c语言](https://img.taocdn.com/s3/m/da63aa08e418964bcf84b9d528ea81c758f52e96.png)
信息论实验哈夫曼编码c语言以下是使用C语言实现哈夫曼编码的示例代码:```cinclude <>include <>include <>define MAX_TREE_HT 100struct MinHeapNode {char data;unsigned freq;struct MinHeapNode left, right;};struct MinHeap {unsigned size;unsigned capacity;struct MinHeapNode array;};struct MinHeapNode newNode(char data, unsigned freq) {struct MinHeapNode temp = (structMinHeapNode)malloc(sizeof(struct MinHeapNode));temp->left = temp->right = NULL;temp->data = data;temp->freq = freq;return temp;}struct MinHeap createMinHeap(unsigned capacity) {struct MinHeap minHeap = (struct MinHeap)malloc(sizeof(struct MinHeap));minHeap->size = 0;minHeap->capacity = capacity;minHeap->array = (struct MinHeapNode)malloc(minHeap->capacity sizeof(struct MinHeapNode));return minHeap;}void swapMinHeapNode(struct MinHeapNode a, struct MinHeapNode b) {struct MinHeapNode t = a;a = b;b = t;}void minHeapify(struct MinHeap minHeap, int idx) {int smallest = idx;int left = 2 idx + 1;int right = 2 idx + 2;if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) {smallest = left;}if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) {smallest = right;}if (smallest != idx) {swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);minHeapify(minHeap, smallest);}}int isSizeOne(struct MinHeap minHeap) {return (minHeap->size == 1);}void insertMinHeap(struct MinHeap minHeap, struct MinHeapNode minHeapNode) {minHeap->size++;int i = minHeap->size - 1;while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {minHeap->array[i] = minHeap->array[(i - 1) / 2];i = (i - 1) / 2;}minHeap->array[i] = minHeapNode;}struct MinHeapNode extractMin(struct MinHeap minHeap) { struct MinHeapNode root = minHeap->array[0];minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size;minHeapify(minHeap, 0);return root;}void buildMinHeap(struct MinHeap minHeap) {int n = minHeap->size - 1;int i;for (i = (n - 1) / 2; i >= 0; --i) {minHeapify(minHeap, i);}}void printArr(int arr[], int n) {int i;for (i = 0; i < n; ++i) {printf("%d", arr[i]);if (i < n - 1) {printf(" ");} else {printf("\n");}}}int isLeaf(struct MinHeapNode root) {return !(root->left) && !(root->right);}void printCodes(struct MinHeapNode root, int arr[], int top) {if (root->left) {arr[top] = 0; // left branch -> 0 in binary tree representation.! So first bit of code for root will be '0'! So, '0' is the prefix for all left branches! Therefore, '。
哈夫曼编码c语言代码
![哈夫曼编码c语言代码](https://img.taocdn.com/s3/m/8ecbe924a31614791711cc7931b765ce04087a7d.png)
哈夫曼编码c语言代码1.统计数据中每个字符出现的次数。
2.根据每个字符出现的次数建立哈夫曼树。
3.根据哈夫曼树构建每个字符的编码,相同的字符具有不同的编码。
4.用编码替换原数据中的字符。
根据上述步骤,我们可以得到以下的C语言实现。
C语言实现哈夫曼编码在C语言中,我们可以使用结构体来表示哈夫曼树节点及其信息:```ctypedef struct node 。
char content;int freq;struct node某 left;struct node某 right;} node;```其中content表示节点所代表的字符,freq表示该字符在数据中出现的次数,left和right分别指向节点的左右子节点。
我们可以使用一个链表来存储所有的字符及其出现的次数:```ctypedef struct listNode 。
node某 n;struct listNode某 ne某t;} listNode;```这个链表可以通过遍历数据,统计每个字符出现的次数来构建。
我们可以使用一个堆来存储所有的树节点,每次从堆中取出频率最小的两个节点,构建一个新的节点,然后将这个新节点插入堆中。
重复这个过程直到堆中只剩下一个根节点,这个节点就是哈夫曼树的根节点。
```ctypedef struct heap 。
int size;node某某 nodes;} heap;```定义堆的时候,size表示堆中节点的数量,nodes是一个数组,存储所有的节点。
我们可以使用一棵二叉堆来实现堆的操作,即将频率最小的节点放在堆的顶部。
构建好哈夫曼树后,我们可以通过遍历树来给每个字符一个独一无二的编码。
编码的时候,我们可以使用一个栈来存储每个节点的信息,然后倒序输出栈中的内容来得到编码。
最后,我们可以使用编码替换原数据中的字符。
在解码的时候,我们只需要将编码反向遍历树即可还原原始数据。
总结。
哈弗曼编码源代码
![哈弗曼编码源代码](https://img.taocdn.com/s3/m/21b4a8dabb4cf7ec4afed0a3.png)
x2=j; } } huff_node[x1].parent=n+i; //将找出的两棵树合并为一颗子树 huff_node[x2].parent=n+i; huff_node[x1].flag=1; huff_node[x2].flag=1; huff_node[n+i].weight=huff_node[x1].weight+huff_node[x2].weight; huff_node[n+i].lchild=x1; huff_node[n+i].rchild=x2; } for(i=0;i<n;i++) //求哈弗曼编码 { cd.start=n; //哈弗吗编码存放在从cd.start到 n的分量上 c=i; p=huff_node[c].parent; while(p!=-1) { if(huff_node[p].lchild==c) cd.bits[cd.start]=0; else cd.bits[cd.start]=1; cd.start=cd.start-1; c=p; p=huff_node[p].parent; } for(j=cd.start+1;j<=n;j++) huff_code[i].bits[j]=cd.bits[j]; huff_code[i].start=cd.start; } fp=fopen("file.txt","w"); if(fp==NULL)
数据结构之哈夫曼编码和解码C源代码
![数据结构之哈夫曼编码和解码C源代码](https://img.taocdn.com/s3/m/146d3a1ca26925c52dc5bf31.png)
玩转算法与数据结构之哈夫曼编码和解码—HIT2000鲁天伟二叉树的一个很重要的应用是生成哈夫曼树来完成哈夫曼编码和解码。
哈夫曼树:假设一个字符串中只有'A','B','C','D','E','F','G'这七个字符,这七个字符出现的权值(也就是出现次数)是3,5,7,6,5,9,8。
我们就以这个字符串作为样本,来进行字符编码,将字符映射成一串二进制码(比如’A’对应000,‘B’对应001),那么最终整个字符串将被编码成一长串二进制码。
我们生成哈夫曼树来进行编码,如下图1所展示就是哈夫曼树最终的模样。
哈夫曼树算法:使用字符数组{'A','B','C','D','E','F','G'},对就权值数组{3,5,7,6,5,9,8};1、我们先从权值数组左边开始,找到数组中未打过使用标记的最小数p和次小数q,以p+q作父结点,p作为左子结点,q作为右子结点。
原则是右子结点权值大于或等于左子结点权值。
把p和q的权值数组位置打标记已使用过,父结点p+q作为新的权值加入到权值数组尾部。
(此例中第一次执行p=3和q=5,对应字符‘A’和‘B’。
把这两个数相加得8,形成新的结点作为父结点。
3作为左子结点,5作为右子结点。
把3和5的权值数组位置打标记已使用过。
父结点权值8作为新的权值加入到权值数组尾部。
)2、重复步骤1,如果叶子结点有N个,那么进行N-1次合并,可以建成哈夫曼树。
图表 1 哈夫曼树编码算法:如上图1所示,所有的字符都出现在叶子结点的位置,从根结点开始遍历,查找每个叶子结点的字符,根到每个叶子结点只有一条路,从根开始向左走标0,向右走标1,根据查找路线,我们可以得出每个叶子结点字符的二进制编码串。
用c++写哈夫曼编码
![用c++写哈夫曼编码](https://img.taocdn.com/s3/m/a98e18ad6394dd88d0d233d4b14e852458fb39f5.png)
用c++写哈夫曼编码以下是使用C++实现哈夫曼编码的示例代码:c复制代码#include<iostream>#include<queue>#include<string>#include<vector>using namespace std;struct TreeNode {char data;int freq;TreeNode *left, *right;TreeNode(char data, int freq) : data(data), freq(freq), left(NULL), right(NULL) {}};struct cmp {bool operator()(const TreeNode *a, const TreeNode *b) {return a->freq > b->freq;}};void printCodes(TreeNode *root, string code) {if (root == NULL) {return;}if (root->left == NULL && root->right == NULL) {cout << root->data << ": " << code << endl;return;}printCodes(root->left, code + "0");printCodes(root->right, code + "1");}void buildHuffmanTree(const vector<char>& data, const vector<int>& freq) { priority_queue<TreeNode*, vector<TreeNode*>, cmp> pq;for (int i = 0; i < data.size(); i++) {pq.push(new TreeNode(data[i], freq[i]));}while (pq.size() > 1) {TreeNode *left = pq.top();pq.pop();TreeNode *right = pq.top();pq.pop();TreeNode *top = new TreeNode('$', left->freq + right->freq);top->left = left;top->right = right;pq.push(top);}TreeNode *root = pq.top();pq.pop();printCodes(root, "");}int main() {vector<char> data = {'a', 'b', 'c', 'd', 'e', 'f'};vector<int> freq = {5, 9, 12, 13, 16, 45};buildHuffmanTree(data, freq);return0;}在这个示例中,我们首先定义了一个结构体TreeNode,表示哈夫曼树的节点。
哈夫曼编码的C语言实现
![哈夫曼编码的C语言实现](https://img.taocdn.com/s3/m/6d64e07b777f5acfa1c7aa00b52acfc789eb9ff9.png)
哈夫曼编码的C语言实现一、大致思路输入信源符号的概率,构造哈夫曼树,从叶子结点到根结点进行编码二、编码实现#include <stdio.h>#define n 7 //leaf number#define m 2*n-1 //all numbertypedef struct{char ch;double weight;int left;int right;int parent;}Node;typedef struct{char ch;int codeis[50];int start;}Code;void HuffmanTree (Node node[],int number){int i,j,x1=0,x2=0;double m1,m2;for(i=0;i<n-1;i++){ //loop n-1m1=m2=1; //least probability p<1//m1 最小 m2第二小for(j=0;j<n+i;j++){if(node[j].weight <m1 && node[j].parent ==-1){m2=m1;x2=x1;m1=node[j].weight;x1=j;} //是最小的else if(node[j].weight <m2 &&node[j].parent ==-1){m2=node[j].weight;x2=j;}} //找结点node[x1].parent = number+i;node[x2].parent = number+i;node[number+i].weight = node[x1].weight + node[x2].weight;node[number+i].left = x1;node[number+i].right = x2;}//end for}int main(int argc, const char * argv[]) {double x[n]={0};printf("请输入%d个符号的概率",n);int i;for(i=0;i<n;i++){scanf("%lf",&x[i]);}Node node[2*n-1]; // 2*len-1 is the number of all nodefor(i=0;i<2*n-1;i++){node[i].weight = 0;node[i].left = -1;node[i].right = -1;node[i].parent = -1;} //initializefor(i=0;i<n;i++){node[i].weight=x[i];}Code code[n],tempcode; //save the code of leafHuffmanTree(node,n); //创建好了哈夫曼树//编码int p,c,j=0;for(i=0;i<n;i++){c=i;tempcode.start = n-1;p=node[c].parent;while(p!=-1){if(node[p].left == c)tempcode.codeis[tempcode.start] = 1; elsetempcode.codeis[tempcode.start] = 0; tempcode.start--;c=p;p=node[c].parent;} //end whilefor(j=tempcode.start+1;j<n;j++){code[i].codeis[j]=tempcode.codeis[j];}//保存下载刚才的结果code[i].start = tempcode.start;} //end forfor (i=0;i<n;i++){for (j=code[i].start+1;j<n;j++){printf("%d",code[i].codeis[j]);}printf("\n");}getchar();return 0;}三、总结1.创建了哈夫曼树,n是叶子结点数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1)内容:利用 Huffman 编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据进行预先编码,在接收端进行解码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/解码系统。
2)要求:一个完整的huffman编解码系统应该具有以下功能:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立Huffman 树,并将它存入hfmTree 中。
编码(Encoding)。
利用已经建好的Huffman树(如果不在内存,则应从文件hfmTree 中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
解码(Decoding)。
利用已经建立好的Huffman树将文件CodeFile中的代码进行解码,结果存入TextFile中。
打印代码文件(Print)。
将文件CodeFile以紧凑的格式显示在终端上,每行 50 个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
打印Huffman树(Tree Printing)。
将已经在内存中的Huffman树以直观的形式(树或者凹入的形式)显示在终端上,同时将此字符形式的Huffman 树写入文件TreePrint中。
3) 测试数据:用下表给出的字符集和频度的实际统计数据建立Huffman树,并对以下报文进行编码和译码:“THIS PROGRAM IS MY FAVORITE”。
完整代码如下:#include<stdio.h>#include<iostream>#include<string>#define N 100int *w;char *c,stack[N],code[N][N];int s1,s2;typedef struct HuffmanTree{int weight;int parent;int lchild;int rchild;}HuffmanTree,*Huff;void menu(void);void Select(struct HuffmanTree HT[],int i);void HuffmanTree(Huff &HT,int *w,int n);void visite(Huff HT,int i,int flag,int rear);void translatef(char *scource,char *save,int n);bool uncodef(FILE *fp1,FILE *fp2,Huff HT,int n);int inputHuff();void screanio(int n);void fileio(int n);int initHuff();void Print_tree(int n,Huff HT);void Convert_tree(Huff HT,unsigned char T[100][100],int tt[100][100],int s,int *i,int j);void decoding(int n);void coding(int n);void main(){int n=0;menu();Huff HT;char state;do{std::cout<<"input:\n";std::cin>>state;fflush(stdin); //读取状态switch(state){case'I':n=inputHuff();HuffmanTree(HT,w,n);std::cout<<"\nHuffmanTree 初始化完毕\n";break;case'C':coding(n);break;case'D':decoding(n);break;case'P':Print_tree(n,HT);break;case'Q':break;}}while(state!='Q');}void menu() //显示菜单函数{std::cout<<"===========HuffmanCoding===========\n";std::cout<<"input \t\t do\n";std::cout<<"I \t\tInit_HUffTree\n"; //初始化huffmantreestd::cout<<"C \t\tCoding\n"; //对ToBeTran.txt文件中的字符进行编码到CodeFile.txt中std::cout<<"D \t\tUnCoding\n"; //对CodeFile.txt中的01序列进行解码到TextFile.txtstd::cout<<"P \t\tPrintTree\n"; //打印哈夫曼树std::cout<<"Q \t\tquit\n";std::cout<<"请初始化哈夫曼树再执行后面的操作\n";}int inputHuff() //输入各个字母及其权值{int i=1,n=0;int ww[28];char cc[28];while(1){std::cout<<"input the letter(input '#' to stop):";cc[i]=std::cin.get();fflush(stdin);if(cc[i]=='#')break;std::cout<<"input the weight:";std::cin>>ww[i];fflush(stdin);n++;i++;}w=(int *)malloc(sizeof(int)*(n+1));c=(char *)malloc(sizeof(char)*(n+1));for(i=0;i<n+1;i++){w[i]=ww[i];c[i]=cc[i];}return n;}void HuffmanTree(Huff &HT,int *w,int n) //初始化哈夫曼树{int m,i;m=n*2-1;HT=(struct HuffmanTree *)malloc(sizeof(struct HuffmanTree)*(m+1));HT[0].lchild=0;HT[0].parent=0;HT[0].rchild=0;HT[0].weight=0;for(i=1;i<m;i++){HT[i].weight=i<=n?w[i]:0;HT[i].lchild=HT[i].rchild=HT[i].parent=0;}for(i=n+1;i<=m;i++){Select(HT,i);HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;HT[s1].parent=HT[s2].parent=i;}}void Select(struct HuffmanTree HT[],int i) //在HT[1..i-1]中选择parent为0且weight为最小的两个结点{int j;for(j=1;j<i;j++){if(HT[j].parent ==0){s1=j;s2=j;goto flag;}}flag: for(j=s1+1;j<i;j++){if(HT[j].parent==0){if(HT[s1].weight >=HT[j].weight){s2=s1;s1=j;}if(HT[s2].weight>HT[j].weight&&j!=s1)s2=j;if(s1==s2)s2=j;}}}void Print_tree(int n,Huff HT) //以凹入法的形式打印树{unsigned char T[100][100];int tt[100][100];int i,j,m=0;FILE *fp;Convert_tree(HT,T,tt,0,&m,2*n-1); //将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中if((fp=fopen("treeprint.txt","wb+"))==NULL)printf("Open file treeprint.txt error!\n");printf("\n以凹凸表形式打印已建好的赫夫曼树:\n");for(i=1;i<=2*n-1;i++){for (j=0;T[i][j]!=0;j++){if(T[i][j]==' ') {printf(" ");fputc(T[i][j],fp);}else{printf("%d",tt[i][j]);fprintf(fp,"%d\n\n\n",tt[i][j]);} }printf("\n");}fclose(fp);printf("\n此字符形式的哈夫曼树已写入文件treeprint.txt中.\n\n");printf("\n文件treeprint.txt的打开方式要为写字板,若打开方式为记事本,则无法显示凹凸表的形式\n");}void Convert_tree(Huff HT,unsigned char T[100][100],int tt[100][100],int s,int *i,int j) //将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中{int k,l;l=++(*i);for(k=0;k<s;k++)T[l][k]=' ';T[l][k]='#';tt[l][k]=HT[j].weight;if(HT[j].lchild)Convert_tree(HT,T,tt,s+1,i,HT[j].lchild);if(HT[j].rchild)Convert_tree(HT,T,tt,s+1,i,HT[j].rchild);T[l][++k]='\0';}void coding(int n) //对文件ToBeTran.txt编码到CodeFile.txt{FILE *fp1;Huff HT;HuffmanTree(HT,w,n);visite(HT,2*n-1,2,0);fflush(stdin);translatef("ToBeTran.txt","CodeFile.txt",n);fp1=fopen("CodeFile.txt","r");printf("\n编码已写入文件treeprint.txt中.\n");fclose(fp1);}void decoding(int n) //对CodeFile.txt中的01序列进行解码到TextFile.txt{FILE *fp1,*fp2;Huff HT;HuffmanTree(HT,w,n);fp1=fopen("CodeFile.txt","r");fp2=fopen("TextFile.txt","w");while(uncodef(fp1,fp2,HT,2*n-1));printf("\n");printf("\n解码已写入文件TextFile.txt中.\n");fclose(fp1);fclose(fp2);}void visite(Huff HT,int i,int flag,int rear)//通过递归调用visite()函数,得到各个字母的编码,存储于全局变量code[][]中{int j=0,k=0;if(flag==0){stack[rear]='0';rear++;}else if(flag==1){stack[rear]='1';rear++;}if(HT[i].lchild==0){for(j=0;j<rear;j++){code[i][j]=stack[j];}code[i][j]='#';rear--;return;}visite(HT,HT[i].lchild,0,rear);visite(HT,HT[i].rchild,1,rear);k=rear;for(j=0;j<k;j++){code[i][j]=stack[j];}code[i][j]='#';rear--;return;}void translatef(char *scource,char *save,int n)//读取文件中的字母序列,并根据code[][]将其转换成01序列输出{FILE *fp1,*fp2;char p=' ';int i=0,j=0,k=0;fp1=fopen(scource,"r");fp2=fopen(save,"w");p=fgetc(fp1);printf("\n得到的编码为:\n");while(p!=EOF){for(i=0;i<=n;i++){if(c[i]==p){for(j=0;j<N&&code[i][j]!='#';j++){fputc(code[i][j],fp2);putchar(code[i][j]);k++;if(k>=50){k=0;putchar('\n');}}}}p=fgetc(fp1);}fclose(fp1);fclose(fp2);}bool uncodef(FILE *fp1,FILE *fp2,Huff HT,int n)//通过对树的访问,把文件中01序列转换成一个字母输出。