赫夫曼树的编码译码
哈夫曼树编码译码实验报告

数据结构课程设计设计题目:哈夫曼树编码译码目录第一章需求分析1第二章设计要求1第三章概要设计2(1)其主要流程图如图1-1所示。
3(2)设计包含的几个方面4第四章详细设计4(1)①哈夫曼树的存储结构描述为:4(2)哈弗曼编码5(3)哈弗曼译码7(4)主函数8(5)显示部分源程序:8第五章调试结果10第六章心得体会12第七章12附录:12第一章需求分析在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。
哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是哈夫曼编码。
哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。
第二章设计要求对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。
通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。
电报通信是传递文字的二进制码形式的字符串。
但在信息传递时,总希望总长度能尽可能短,即采用最短码。
假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。
若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。
C++哈夫曼树编码和译码的实现

C++哈夫曼树编码和译码的实现⼀.背景介绍: 给定n个权值作为n个叶⼦结点,构造⼀棵⼆叉树,若带权路径长度达到最⼩,称这样的⼆叉树为最优⼆叉树,也称为哈夫曼树(Huffman Tree)。
哈夫曼树是带权路径长度最短的树,权值较⼤的结点离根较近。
⼆.实现步骤: 1.构造⼀棵哈夫曼树 2.根据创建好的哈夫曼树创建⼀张哈夫曼编码表 3.输⼊⼀串哈夫曼序列,输出原始字符三.设计思想: 1.⾸先要构造⼀棵哈夫曼树,哈夫曼树的结点结构包括权值,双亲,左右孩⼦;假如由n个字符来构造⼀棵哈夫曼树,则共有结点2n-1个;在构造前,先初始化,初始化操作是把双亲,左右孩⼦的下标值都赋为0;然后依次输⼊每个结点的权值2.第⼆步是通过n-1次循环,每次先找输⼊的权值中最⼩的两个结点,把这两个结点的权值相加赋给⼀个新结点,,并且这个新结点的左孩⼦是权值最⼩的结点,右孩⼦是权值第⼆⼩的结点;鉴于上述找到的结点都是双亲为0的结点,为了下次能正确寻找到剩下结点中权值最⼩的两个结点,每次循环要把找的权值最⼩的两个结点的双亲赋值不为0(i).就这样通过n-1循环下、操作,创建了⼀棵哈夫曼树,其中,前n 个结点是叶⼦(输⼊的字符结点)后n-1个是度为2的结点3.编码的思想是逆序编码,从叶⼦结点出发,向上回溯,如果该结点是回溯到上⼀个结点的左孩⼦,则在记录编码的数组⾥存“0”,否则存“1”,注意是倒着存;直到遇到根结点(结点双亲为0),每⼀次循环编码到根结点,把编码存在编码表中,然后开始编码下⼀个字符(叶⼦)4.译码的思想是循环读⼊⼀串哈夫曼序列,读到“0”从根结点的左孩⼦继续读,读到“1”从右孩⼦继续,如果读到⼀个结点的左孩⼦和右孩⼦是否都为0,如果是说明已经读到了⼀个叶⼦(字符),翻译⼀个字符成功,把该叶⼦结点代表的字符存在⼀个存储翻译字符的数组中,然后继续从根结点开始读,直到读完这串哈夫曼序列,遇到结束符便退出翻译循环四.源代码:1/***************************************2⽬的:1.根据输⼊的字符代码集及其权值集,3构造赫夫曼树,输出各字符的赫夫曼编码42.输⼊赫夫曼码序列,输出原始字符代码5作者:Dmego 时间:2016-11-116****************************************/7 #include<iostream>8#define MAX_MA 10009#define MAX_ZF 10010using namespace std;1112//哈夫曼树的储存表⽰13 typedef struct14 {15int weight; //结点的权值16int parent, lchild, rchild;//双亲,左孩⼦,右孩⼦的下标17 }HTNode,*HuffmanTree; //动态分配数组来储存哈夫曼树的结点1819//哈夫曼编码表的储存表⽰20 typedef char **HuffmanCode;//动态分配数组存储哈夫曼编码2122//返回两个双亲域为0且权值最⼩的点的下标23void Select(HuffmanTree HT, int n, int &s1, int &s2)24 {25/*n代表HT数组的长度26*/2728//前两个for循环找所有结点中权值最⼩的点(字符)29for (int i = 1; i <= n; i++)30 {//利⽤for循环找出⼀个双亲为0的结点31if (HT[i].parent == 0)32 {33 s1 = i;//s1初始化为i34break;//找到⼀个后⽴即退出循环35 }36 }37for (int i = 1; i <= n; i++)38 {/*利⽤for循环找到所有结点(字符)权值最⼩的⼀个39并且保证该结点的双亲为0*/40if (HT[i].weight < HT[s1].weight && HT[i].parent == 0)41 s1 = i;42 }43//后两个for循环所有结点中权值第⼆⼩的点(字符)44for (int i = 1; i <= n; i++)45 {//利⽤for循环找出⼀个双亲为0的结点,并且不能是s146if (HT[i].parent == 0 && i != s1)47 {48 s2 = i;//s2初始化为i49break;//找到⼀个后⽴即退出循环50 }51 }5253for (int i = 1; i <= n; i++)54 {/*利⽤for循环找到所有结点(字符)权值第⼆⼩的⼀个,55该结点满⾜不能是s1且双亲是0*/56if (HT[i].weight < HT[s2].weight && HT[i].parent == 0 && i!= s1)57 s2 = i;58 }5960 }6162//构造哈夫曼树63void CreateHuffmanTree(HuffmanTree &HT, int n)64 {65/*-----------初始化⼯作-------------------------*/66if (n <= 1)67return;68int m = 2 * n - 1;69 HT = new HTNode[m + 1];70for (int i = 1; i <= m; ++i)71 {//将1~m号单元中的双亲,左孩⼦,右孩⼦的下标都初始化为072 HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0;73 }74for (int i = 1; i <= n; ++i)75 {76 cin >> HT[i].weight;//输⼊前n个单元中叶⼦结点的权值77 }78/*-----------创建⼯作---------------------------*/79int s1,s2;80for (int i = n + 1; i <= m; ++i)81 {//通过n-1次的选择,删除,合并来构造哈夫曼树82 Select(HT, i - 1, s1, s2);83/*cout << HT[s1].weight << " , " << HT[s2].weight << endl;*/84/*将s1,s2的双亲域由0改为i85 (相当于把这两个结点删除了,这两个结点不再参与Select()函数)*/86 HT[s1].parent = i;87 HT[s2].parent = i;88//s1,与s2分别作为i的左右孩⼦89 HT[i].lchild = s1;90 HT[i].rchild = s2;91//结点i的权值为s1,s2权值之和92 HT[i].weight = HT[s1].weight + HT[s2].weight;93 }94 }9596//从叶⼦到根逆向求每个字符的哈夫曼编码,储存在编码表HC中97void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)98 {99 HC = new char*[n + 1];//分配储存n个字符编码的编码表空间100char *cd = new char[n];//分配临时存储字符编码的动态空间101 cd[n - 1] = '\0';//编码结束符102for (int i = 1; i <= n; i++)//逐个求字符编码103 {104int start = n - 1;//start 开始指向最后,即编码结束符位置105int c = i;106int f = HT[c].parent;//f指向结点c的双亲107while (f != 0)//从叶⼦结点开始回溯,直到根结点108 {109 --start;//回溯⼀次,start向前指向⼀个位置110if (HT[f].lchild == c) cd[start] = '0';//结点c是f的左孩⼦,则cd[start] = 0; 111else cd[start] = '1';//否则c是f的右孩⼦,cd[start] = 1112 c = f;113 f = HT[f].parent;//继续向上回溯114 }115 HC[i] = new char[n - start];//为第i个字符编码分配空间116 strcpy(HC[i], &cd[start]);//把求得编码的⾸地址从cd[start]复制到HC的当前⾏中117 }118delete cd;119 }120121//哈夫曼译码122void TranCode(HuffmanTree HT,char a[],char zf[],char b[],int n)123 {124/*125 HT是已经创建好的哈夫曼树126 a[]⽤来传⼊⼆进制编码127 b[]⽤来记录译出的字符128 zf[]是与哈夫曼树的叶⼦对应的字符(叶⼦下标与字符下标对应)129 n是字符个数,相当于zf[]数组得长度130*/131132int q = 2*n-1;//q初始化为根结点的下标133int k = 0;//记录存储译出字符数组的下标134int i = 0;135for (i = 0; a[i] != '\0';i++)136 {//for循环结束条件是读⼊的字符是结束符(⼆进制编码)137//此代码块⽤来判断读⼊的⼆进制字符是0还是1138if (a[i] == '0')139 {/*读⼊0,把根结点(HT[q])的左孩⼦的下标值赋给q140下次循环的时候把HT[q]的左孩⼦作为新的根结点*/141 q = HT[q].lchild;142 }143else if (a[i] == '1')144 {145 q = HT[q].rchild;146 }147//此代码块⽤来判断HT[q]是否为叶⼦结点148if (HT[q].lchild == 0 && HT[q].rchild == 0)149 {/*是叶⼦结点,说明已经译出⼀个字符150该字符的下标就是找到的叶⼦结点的下标*/151 b[k++] = zf[q];//把下标为q的字符赋给字符数组b[]152 q = 2 * n - 1;//初始化q为根结点的下标153//继续译下⼀个字符的时候从哈夫曼树的根结点开始154 }155 }156/*译码完成之后,⽤来记录译出字符的数组由于没有结束符输出的157时候回报错,故紧接着把⼀个结束符加到数组最后*/158 b[k] = '\0';159 }160//菜单函数161void menu()162 {163 cout << endl;164 cout << " ┏〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┓" << endl;165 cout << " ┃★★★★★★★哈夫曼编码与译码★★★★★★★┃" << endl;166 cout << " ┃ 1. 创建哈夫曼树┃" << endl;167 cout << " ┃ 2. 进⾏哈夫曼编码┃" << endl;168 cout << " ┃ 3. 进⾏哈夫曼译码┃" << endl;169 cout << " ┃ 4. 退出程序┃" << endl;170 cout << " ┗〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓┛" << endl;171 cout << " <><注意:空格字符⽤'- '代替><>" << endl;172 cout << endl;173 }174void main()175 {176int falg;//记录要编码的字符个数177char a[MAX_MA];//储存输⼊的⼆进制字符178char b[MAX_ZF];//存储译出的字符179char zf[MAX_ZF];//储存要编码的字符180 HuffmanTree HT = NULL;//初始化树为空数181 HuffmanCode HC = NULL;//初始化编码表为空表182 menu();183while (true)184 {185int num;186 cout << "<><请选择功能(1-创建 2-编码 3-译码 4-退出)><>: ";187 cin >> num;188switch (num)189 {190case1 :191 cout << "<><请输⼊字符个数><>:";192 cin >> falg;193//动态申请falg个长度的字符数组,⽤来存储要编码的字符194/*char *zf = new char[falg];*/195 cout << "<><请依次输⼊" << falg << "个字符:><>: ";196for (int i = 1; i <= falg; i++)197 cin >> zf[i];198 cout << "<><请依次输⼊" << falg << "个字符的权值><>: ";199 CreateHuffmanTree(HT, falg);//调⽤创建哈夫曼树的函数200 cout << endl;201 cout << "<><创建哈夫曼成功!,下⾯是该哈夫曼树的参数输出><>:" << endl;202 cout << endl;203 cout << "结点i"<<"\t"<<"字符" << "\t" << "权值" << "\t" << "双亲" << "\t" << "左孩⼦" << "\t" << "右孩⼦" << endl;204for (int i = 1; i <= falg * 2 - 1; i++)205 {206 cout << i << "\t"<<zf[i]<< "\t" << HT[i].weight << "\t" << HT[i].parent << "\t" << HT[i].lchild << "\t" << HT[i].rchild << endl; 207 }208 cout << endl;209break;210case2:211 CreatHuffmanCode(HT, HC, falg);//调⽤创建哈夫曼编码表的函数212 cout << endl;213 cout << "<><⽣成哈夫曼编码表成功!,下⾯是该编码表的输出><>:" << endl; 214 cout << endl;215 cout << "结点i"<<"\t"<<"字符" << "\t" << "权值" << "\t" << "编码" << endl; 216for (int i = 1; i <= falg; i++)217 {218 cout << i << "\t"<<zf[i]<< "\t" << HT[i].weight << "\t" << HC[i] << endl; 219 }220 cout << endl;221break;222case3:223 cout << "<><请输⼊想要翻译的⼀串⼆进制编码><>:";224/*这样可以动态的直接输⼊⼀串⼆进制编码,225因为这样输⼊时最后系统会⾃动加⼀个结束符*/226 cin >> a;227 TranCode(HT, a, zf, b, falg);//调⽤译码的函数,228/*这样可以直接把数组b输出,因为最后有229在数组b添加输出时遇到结束符会结束输出*/230 cout << endl;231 cout << "<><译码成功!翻译结果为><>:" << b << endl;232 cout << endl;233break;234case4:235 cout << endl;236 cout << "<><退出成功!><>" << endl;237 exit(0);238default:239break;240 }241 }242243//-abcdefghijklmnopqrstuvwxyz244//186 64 13 22 32 103 21 15 47 57 1 5 32 20 57 63 15 1 48 51 80 23 8 18 1 16 1245//000101010111101111001111110001100100101011110110246247 }哈夫曼编码译码五.运⾏截图:。
数据结构哈夫曼树编码及译码的实现实验报告

实验:哈夫曼树编码及译码的实现一.实验题目给定字符集的HUFFMANN编码与解码,这里的字符集及其字符频数自己定义,要求输出个字符集的哈夫曼编码及给定的字符串的哈夫曼码及译码结果。
二.实验原理首先规定构建哈夫曼树,然后进行哈夫曼树的编码,接着设计函数进行字符串的编码过程,最后进行哈夫曼编码的译码。
首先定义一个结构体,这个结构体定义时尽可能的大,用来存放左右的变量,再定义一个地址空间,用于存放数组,数组中每个元素为之前定义的结构体。
输入n个字符及其权值。
构建哈夫曼树:在上述存储结构上实现的哈夫曼算法可大致描述为:1.首先将地址空间初始化,将ht[0…n-1]中所有的结点里的指针都设置为空,并且将权值设置为0.2.输入:读入n个叶子的权值存于向量的前n个分量中。
它们是初始森林中n个孤立的根结点上的权值。
3.合并:对森林中的树共进行n-1次合并,所产生的新结点依次放入向量ht的第i个分量中。
每次合并分两步:①在当前森林ht[0…i-1]的所有结点中,选取权最小和次小的两个根结点[s1]和 [s2]作为合并对象,这里0≤s1,s2≤i-1。
②将根为ht[s1]和ht[s2]的两棵树作为左右子树合并为一棵新的树,新树的根是新结点ht[i]。
具体操作:将ht[s1]和ht[s2]的parent置为i,将ht[i]的lchild和rchild分别置为s1和s2 .新结点ht[i]的权值置为ht[s1]和ht[s2]的权值之和。
4.哈夫曼的编码:约定左子为0,右子为1,则可以从根结点到叶子结点的路径上的字符组成的字符串作为该叶子结点的编码。
当用户输入字母时。
就在已经找好编码的编码结构体中去查找该字母。
查到该字母就打印所存的哈夫曼编码。
接着就是完成用户输入0、1代码时把代码转成字母的功能。
这是从树的头结点向下查找,如果当前用户输入的0、1串中是0则就走向该结点的左子。
如果是1这就走向该结点的右结点,重复上面步骤。
树的应用 哈夫曼编编码 和 译码

华%%%%%%%%%%%%%%%%%%学院数据结构实验报告2011~2012学年第二学期2011级计算机专业班级:学号:姓名:实验三树的应用一、实验题目:树的应用——哈夫曼编/译码二、实验内容:利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。
根据哈夫曼编码的原理,编写一个程序,在用户输入字符及权值的基础上求哈夫曼编码。
要求:(1)从键盘输入字符集(字母a~z,空格)共27个字符,以及出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,并输出数组ht[]的初态和终态。
(2)对各个字符进行哈夫曼编码,打印输出字符及对应的哈夫曼编码。
(3)编码:从键盘输入字符串,利用已建好的哈夫曼编码,实现该字符串的编码。
(4)(选作)译码:从键盘输入二进制串,利用已建好的哈夫曼编码,将二进制串还原为字符串。
三、程序源代码:typedef struct{char data;int weight;int parent;int lchild;int rchild;}HTNode;typedef struct{char cd[100];int start;}HCode;//这里保存字母对应的编码,我本来想用指向字符数组的指针数组,可是后来想到利用结构体更简单。
struct Codes{char ch;char codes[27];};#include<iostream.h>#include<stdio.h>#include<string.h>const int maxsize=100;//特色,动态编码void tongji(char str[],int *pinlv);void createHT(HTNode *ht,int n,int pinlv[]);void showHT(HTNode ht[],int n);void createHcode(HTNode ht[],HCode* hcd,int n);void showHCode(HCode hcd[],int n,int pinlv[]);//使字符与编码对应void matchcodes(HCode hcd[],int pinlv[],int n,Codes* code);void charToCode(Codes codes[],char *str);void codeToChar(Codes codes[]);void main(){cout<<"本例实现动态编码:根据输入的字符串建立编码规则,然后按此规则对输入的字符串进行编码,对输入的编码进行译码操作"<<endl;//输入cout<<"input a string"<<endl;char str[maxsize];gets(str);//统计int pinlv[27];int len=0;for(int i=0;i<27;i++)pinlv[i]=0;tongji(str,pinlv);for(int k=0;k<27;k++)if(pinlv[k]!=0)len++;cout<<len<<endl;// cout<<pinlv[26]<<endl;//构造哈夫曼树HTNode ht[199];createHT(ht,len,pinlv);//哈夫曼编码HCode hcd[27];createHcode(ht,hcd,len);showHCode(hcd,len,pinlv);//字符与编码对应匹配Codes codes[27];matchcodes(hcd,pinlv,len,codes);//char to codecharToCode(codes,str);// code to charcodeToChar(codes);}//这个函数有错误,已经改正void codeToChar(Codes codes[]){cout<<"根据上面输出的编码规则,请输入要译码的01编码(相邻编码要以逗号分割,以“#”结束)"<<endl;char str[100];gets(str);cout<<str<<"的译码为:"<<endl;char temp[27]; //保存每个字符的编码,每次要赋 0 啊int i,j;for(i=0,j=0;i<100;i++){if(str[i]!=','){temp[j]=str[i];j++;}else{temp[j]='\0';for(int k=0;k<27;k++){if(strcmp(codes[k].codes ,temp)==0){cout<<codes[k].ch <<" ";//cout.flush();break;}}j=0; //赋0 操作}if(str[i]=='#'){break;}}cout<<endl;}void charToCode(Codes codes[],char *str){char ch=*str;int k=0;cout<<str<<"的编码为:"<<endl;while(ch!='\0'){for(int i=0;i<27;i++){if(codes[i].ch ==ch)cout<<codes[i].codes<<",";}k++;ch=*(str+k);}cout<<endl;}//已经改进过的地方void matchcodes(HCode hcd[],int pinlv[],int n,Codes* codes) {int i,k,m;char ch='a';int p=0;char temp[27];for(int z=0;z<26;z++){temp[z]=' ';}temp[26]='\0';for(i=0;i<27;i++){if(pinlv[i]!=0){ch='a';ch=char(ch+i);if(ch>='a'&&ch<='z'){codes[p].ch =ch;//测试/* if(codes[p].ch==ch){cout<<"succss"<<endl;}*/}elsecodes[p].ch =' ';m=0;for(k=hcd[p].start;k<=n;k++){temp[m]=hcd[p].cd [k];m++;}//字符串必须给出结束符位置,否则会输出乱码啊temp[m]='\0';//codes[p]=temp;strcpy(codes[p].codes ,temp);// cout<<codes[p].ch;// cout<<codes[p].ch<<"-----"<<codes[p].codes<<endl;p++;}}}void showHCode(HCode hcd[],int n,int pinlv[]){int i,k;char ch='a';int p=0;cout<<"字符"<<" "<<"对应编码"<<endl;for(i=0;i<27;i++){//每次必须从字符'a'开始ch='a';////ch=char(ch+i);if(pinlv[i]!=0){if(ch>='a'&&ch<='z')cout<<ch<<" ";elsecout<<" "<<" ";for(k=hcd[p].start;k<=n;k++)cout<<hcd[p].cd [k];p++;cout<<endl;}}}void createHcode(HTNode ht[],HCode* hcd,int n) {int i,f,c;HCode hc;for(i=0;i<n;i++){//不是书上的hc.start =n;hc.start =n-1;c=i;f=ht[i].parent ;while(f!=-1){if(ht[f].lchild ==c)hc.cd [hc.start --]='0';elsehc.cd [hc.start --]='1';c=f;f=ht[f].parent ;}//最后一位必须赋值为结束符hc.cd[n]='\0';hc.start ++;hcd[i]=hc;}}void createHT(HTNode* ht,int n,int pinlv[]){for(int m=0;m<=2*n-1;m++)//初始化节点的所有与域值ht[m].parent =ht[m].lchild =ht[m].rchild =-1;char ch='a';int p=0;for(int z=0;z<27;z++)//循环27个字母(a-z和''),若频数大于0,就创建节点{if(pinlv[z]!=0){if(ch>='a'&&'z'>=ch){ht[p].data =ch;ht[p].weight =pinlv[ch-97];}else{ht[p].data =' ';ht[p].weight =pinlv[26];}p++;}ch=char (ch+1);}cout<<"ht[]初态输出 ";showHT(ht,n);int i,k,lnode,rnode;int min1,min2;for(i=n;i<2*n-1;i++){min1=min2=32767;lnode=rnode=-1;for(k=0;k<=i-1;k++){if(ht[k].parent ==-1){if(ht[k].weight <min1){min2=min1;rnode=lnode;min1=ht[k].weight ;lnode=k;}else if(ht[k].weight <min2){min2=ht[k].weight ;rnode=k;}}}ht[lnode].parent =i;ht[rnode].parent =i;ht[i].weight =ht[lnode].weight +ht[rnode].weight ;ht[i].lchild =lnode;ht[i].rchild =rnode;ht[i].data ='*';}cout<<"ht[]终态输出 ";showHT(ht,2*n-1);}void tongji(char str[],int *pinlv){char ch=*str;int k=1;while(ch!='\0'){ if(ch>='a'&&'z'>=ch)pinlv[ch-97]+=1;elsepinlv[26]+=1;ch=*(str+k);k++;}}void showHT(HTNode ht[],int n){ cout<<"节点信息如下:"<<endl;cout<<"data"<<" "<<"weig"<<" "<<"pare"<<" "<<"lchd"<<" "<<"rchd"<<endl;for(int i=0;i<n;i++){cout<<ht[i].data <<" "<<ht[i].weight <<" "<<ht[i].parent <<" "<<ht[i].lchild <<" "<<ht[i].rchild <<endl;}}四、测试结果:五、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)注:内容一律使用宋体五号字,单倍行间距通过本次实验,我感觉到自己的程序编程细节问题必须注意:如使用gets()函数可接收带有空格的输入字符串;在进行编码译码时,必须注意,数组的上下界问题。
哈夫曼编码与译码完整版

《数据结构》哈夫曼编码与译码实验报告题目:哈夫曼编码与译码班级:xxxx学号:xxxxxxxxxxx姓名:xxx完成时间:2012年12月19日一、程序总体结构主程序main显示系统时间showtime() 给用户提供选择方式chioce1()显示界面告诉用户程序名称show()打开文件进行加密openfile()退出程序输入电文进行加密input()将输入(文件中)的电文进行哈夫曼编码CrtHuffmanCode(ht,hc,n)统计输入(文件中)字母的出现频率CrW(data,w,count)【fcount(alldata,data,count)】输出每一个字母所对应的哈夫曼编码Printf(hc,n,data,alldata,count)将输入(文件中)的电文创建成哈夫曼树CrtHuffmantree(ht,w,n)对输入(文件中)的文字进行哈夫曼加密showall(hc,alldata,count,data,n)下面有几个不同的程序供选着参考:程序源代码:#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].rchil d<<"\t"<<endl;}outfile.close();cout<<"初始化结果已保存在hfmTree文件中\n";}void ToBeTree() //将正文写入文件ToBeTree中{ofstream outfile;outfile.open("ToBeTree.txt",ios::out);outfile<<"THIS PROGRAM IS MYFAVORITE";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')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;}{ 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);}}源程序:#include<iostream>#include<fstream>#include<iomanip>#include<vector>using namespace std;typedef struct //节点结构{char data; //记录字符值long int weight; //记录字符权重unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树typedef char * *HuffmanCode; //动态分配数组存储哈夫曼编码表void Select(HuffmanTree &HT,int i,int &s1,int &s2) //在HT[1...t]中选择parent不为0且权值最小的两个结点,其序号分别为s1和s2{s1=0;s2=0;int n1=30000,n2=30000;for(int k=1;k<=i;k++){if(HT[k].parent==0){if(HT[k].weight<n1){n2=n1; n1=HT[k].weight;s2=s1; s1=k;}elseif(HT[k].weight<n2){n2=HT[k].weight;s2=k;}}}}void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n)//将要编码的字符串存入空树中{ifstream fin1("zifu.txt");ifstream fin2("weight.txt");if(n<=1)return;int m=2*n-1;int i;HT=new HTNode[m+1];char *zifu;int *weight;zifu= new char[n+1];weight=new int[n+1];for(i=1;i<=n;i++)//将待编码的字符放在zifu数组中{char ch;ch=fin1.get();zifu[i]=ch;}for(i=1;i<=n;i++)//将带编码字符对应的权值放在weight数组中{fin2>>weight[i];}for( i=1;i<=n;i++){HT[i].data=zifu[i];HT[i].weight=weight[i];}for(i=n+1;i<=m;i++){HT[i].data='@';}for(i=1;i<=m;i++){HT[i].parent=HT[i].lchild=HT[i].rchild=0;}for(i=n+1;i<=m;++i){int s1,s2;Select(HT,i-1,s1,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;}HC=(HuffmanCode)malloc((n+1)*sizeof(char*));开辟一个求编码的工作空间char *cd;cd=(char *)malloc(n*sizeof(char));//开辟空间存放权值cd[n-1]='\0';for(i=1;i<=n;i++){int start=n-1;int c,f;for( c=i, f=HT[i].parent;f!=0;c=f,f=HT[f].parent)//从叶子到根逆向求编码{if(HT[f].lchild==c)cd[--start]='0';//若是左孩子编为'0'elsecd[--start]='1';//若是右孩子编为'1'}HC[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间strcpy(HC[i],&cd[start]);}delete []cd; //释放工作空间}void printHuffmanTree(HuffmanTree HT,int n) //显示有n个叶子结点的哈夫曼树的编码表{ ofstream fout("hfmtree.txt"); //将对应字符的的哈弗曼树存入cout<<"NUM"<<" "<<"data"<<" "<<"weight"<<" "<<"parent"<<" "<<"lchild"<<" "<<"rchlid"<<endl;for(int i=1;i<=2*n-1;i++){fout<<HT[i].weight<<setw(3)<<HT[i].parent<<setw(3)<<HT[i].lchild<<setw(3) <<HT[i].rchild<<endl;cout<<i<<setw(5)<<HT[i].data<<setw(3)<<HT[i].weight<<setw(3)<<HT[i].pare nt<<setw(3)<<HT[i].lchild<<setw(3)<<HT[i].rchild<<endl;}}void printHuffmanCoding(HuffmanTree HT,HuffmanCode HC,int n)//输出字符的对应哈弗曼编码并存入code.txt文件{cout<<"Huffman code is:"<<endl;ofstream fout("code.txt");for(int i=1;i<=n;i++){cout<<HT[i].data<<" --> ";cout<<(HC[i])<<endl;fout<<(HC[i])<<endl;}}void code_file(HuffmanTree HT,HuffmanCode HC,int n)//对文件tobetran.txt进行编码,并将编码存入codefile文件中{ifstream fin("tobetran.txt");ofstream fout("codefile.txt");vector<char> a;char ch;while((ch=fin.get())!='*')a.push_back(ch);cout<<"待编码的字符串为:";for(int k=0;k<a.size();k++)cout<<a[k];cout<<endl;cout<<"\n编码结果:"<<endl;for(int i=0;i<a.size();i++){for(int j=1;j<=n;j++){if(a[i]==HT[j].data){fout<<HC[j];break;}}}fin.close();fout.close();}void Decoding(HuffmanTree HT,HuffmanCode HC,int n)//打开codefile文件并对文件内容进行译码{int const m=2*n-1;ifstream fin("codefile.txt");ofstream fout("textfile.txt");vector<char> a;for(char c;fin>>c;)a.push_back(c);int count=0;for(int k=0;k<a.size();k++){cout<<a[k];count++;if(count%50==0)cout<<endl;}int i=0;int p; //用p来记住m的值cout<<endl;cout<<"\n译码结果:"<<endl;while(i<a.size()){p=m; //从哈弗曼数的根开始遍历while(HT[p].lchild){if(a[i]=='1')p=HT[p].rchild;elsep=HT[p].lchild;i++;}fout<<HT[p].data;cout<<HT[p].data;}}void main(){int n;cout<<"输入权值个数:"; //设置权值数值cin>>n;printf("\n");HuffmanTree HT; //哈夫曼树HTHuffmanCode HC; //哈夫曼编码表HCHuffmanCoding(HT,HC,n); //进行哈夫曼编码printHuffmanCoding(HT,HC,n); //显示编码的字符printf("\n");code_file(HT,HC,n); //显示要编码的字符串,并把编码值显示出来Decoding(HT,HC,n); //译码并显示译码后的字符串printf("\n\n\n");system("pause");}主要程序代码://HuffmanCode1.h#ifndef HUFFMAMCODE_H#define HUFFMAMCODE_H#include<iostream>#include<fstream>using namespace std;struct HuffmanNode //定义哈夫曼树各结点{int weight;int parent;int lchild,rchild;int flag;};class HuffmanCode1 //哈夫曼编码类{public:char Info[100];int Start;char Leaf;};class HuffmanTree1 //建立哈夫曼树类{private:HuffmanNode *Node;public:int f;HuffmanCode1 *hf;HuffmanTree1();~HuffmanTree1();void TranslatedCode();void CodeHuf(HuffmanNode a[],HuffmanCode1 b[],int n);void CreateHfmTree(char Str[],int m[],int n);void TransCode(HuffmanCode1 b[],int n) ;void TranslateArtcle(HuffmanCode1 b[],int n) ;};#endif //HUFFMAMCODE_HHuffmanCode.cpp#include "iostream"#include<stdio.h>#include "math.h"#include "stdlib.h"#include"HuffmanCode1.h"#include<string>using namespace std;#define MAXDA TA 10000 //最长字符串#define MAXSIZE 150 //最多子叶数//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////第一部分功能(W)实现的代码$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ HuffmanTree1::HuffmanTree1(){ Node=NULL; } //将树结点初始化为空HuffmanTree1::~HuffmanTree1(){ delete[] Node; } //释放结点空间void HuffmanTree1::CreateHfmTree(char Str[],int m[],int n)//建立哈夫曼树{int i,j,m1,m2,x1,x2;HuffmanNode *HfmNode=new HuffmanNode[2*n-1];HuffmanCode1 *HfmCode=new HuffmanCode1[n];for(i=0;i<2*n-1;i++){HfmNode[i].weight=0;HfmNode[i].parent=0;HfmNode[i].flag=0;HfmNode[i].lchild=-1;HfmNode[i].rchild=-1;}for(i=0;i<n;i++){HfmNode[i].weight=m[i];HfmCode[i].Leaf=Str[i];}for(i=0;i<n-1;i++){m1=m2=32767;x1=x2=0;for(j=0;j<n+i;j++){if(HfmNode[j].weight<=m1&&HfmNode[j].flag==0){m2=m1;x2=x1;m1=HfmNode[j].weight;x1=j;}else if(HfmNode[j].weight<=m2&&HfmNode[j].flag==0){m2=HfmNode[j].weight;x2=j;}}HfmNode[x1].parent=n+i;HfmNode[x2].parent=n+i;HfmNode[x1].flag=1;HfmNode[x2].flag=1;HfmNode[n+i].weight=HfmNode[x1].weight+HfmNode[x2].weight;HfmNode[n+i].lchild=x1;HfmNode[n+i].rchild=x2;}CodeHuf(HfmNode,HfmCode,n);TransCode(HfmCode,n);//TranslateArtcle(HfmCode,n);hf=HfmCode; f=n;}void HuffmanTree1::CodeHuf(HuffmanNode a[],HuffmanCode1 b[],int n) //对哈夫曼树进行编码{HuffmanCode1 Hfd;int c,p;for(int i=0;i<n;i++){Hfd.Start=n-1;c=i;p=a[c].parent;while(p!=0){if(a[p].lchild==c)[Hfd.Start]='0';else[Hfd.Start]='1';Hfd.Start--;c=p;p=a[c].parent;}printf("%c :",b[i].Leaf);for(int j=Hfd.Start+1;j<n;j++){b[i].Info[j]=[j];printf("%c",[j]);}printf("\n");b[i].Start=Hfd.Start;}}void HuffmanTree1::TransCode(HuffmanCode1 b[],int n) //对文章进行翻译并保存{ifstream ifs("WData.txt");ofstream ofs("WCode.txt");char s[1000];int t=0;char ch;cout<<"************************************************************** *****************"<<endl;printf("报文的编码为:\n");while(ifs.get(ch)){if(ch!='\n')s[t]=ch;for(int i=0;i<n;i++){if(s[t]==b[i].Leaf)for(int j=b[i].Start+1;j<n;j++){printf("%c",b[i].Info[j]);ofs<<b[i].Info[j];}}t++;}printf("\n");printf("报文的编码已经保存在WCode.txt中\n");cout<<"*********************************************************** ********************"<<endl;}void HuffmanTree1::TranslateArtcle(HuffmanCode1 b[],int n) //将所译的码翻译成文章并保存{int t=0;ifstream ifs("WCode.txt");ofstream ofs("TransWData.txt");string s;getline(ifs,s);for(t=0;s[t]!='\0';t++);int l=0;int j=0;printf("报文的译码结果为:\n");while(l<t){while(j<n){int hu=b[j].Start+1;int k=0;while(hu<n){if(s[l]==b[j].Info[hu]){l++;hu++;k++;}else{break;}}if(hu==n){printf("%c",b[j].Leaf);ofs<<b[j].Leaf;j=0;break;}else{l=l-k;j++; continue;}}}printf("\n");printf("译码的结果已经保存到TransWData.txt中\n");cout<<"*********************************************************** ********************"<<endl;}void HuffmanTree1::TranslatedCode(){ifstream ifs("WData.txt");char str[1000];char Str[100];int i=0,j,m[100],h,k=0;int n=0;cout<<"*********************************************************** ********************"<<endl;printf("文件中提取的文章字符串是:\n");char ch;while(ifs.get(ch)){printf("%c",ch);if(ch!='\n'){str[n++]=ch;}}printf("\n");printf("字符串中共含有字符%d个\n",n);for(i=0;i<n;i++){j=0;h=0;while(str[i]!=str[j])j++;if(j==i){Str[k]=str[i];printf("字符%c出现",Str[k]);}elsecontinue;for(j=i;j<n;j++){if(str[i]==str[j])h++;}printf("%d次\n",h);m[k]=h;k++;}cout<<"*********************************************************** ********************"<<endl;printf("字符串中字符种类有%d种\n",k);cout<<"*********************************************************** ********************"<<endl;printf("每个字符对应的哈夫曼编码是:\n");CreateHfmTree(Str,m,k);cin.get();// printf("\n");}//main.cpp//#include"HuffmanCode1.h"//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////第二部分功能实现的代码$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ typedef struct //哈弗曼树节点的结构体{char info; //关联字符信息unsigned int weight; //每个节点的权职unsigned int parent, lchild, rchild;}HTNode,*HuffmanTree;typedef char **HuffmanCode; //存储哈弗曼编码void Select(HuffmanTree HT, int j,int &s1,int &s2){ //选择双亲节点为0,并且最小的两个子叶节点int i=1,m;while(HT[i].parent!=0)i++; //找第一个双亲节点为0的子叶结点for(s2=s1=i;i<j;i++){ /保证s1中的权值最小,s2次小if(HT[i].parent==0 && HT[i].weight<HT[s1].weight){s2=s1;s1=i;}else if(HT[i].parent==0 && HT[i].weight>=HT[s1].weight &&HT[i].weight<=HT[s2].weight)s2=i;while(HT[i].parent==0 && s1==s2){m=i;m++;while(HT[m].parent!=0)m++;s2=m;}}}void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n, char *info){ //哈弗曼编码int i,m;HuffmanTree p;if(n<1) return;m = 2*n-1;HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));for(p=HT+1,i=1;i<=n;++i,++p,++w,++info){ //初始化所有已存在的子叶信息p->info = *info;p->weight = *w;p->parent = 0;p->lchild = 0;p->rchild = 0;}//forfor(; i<=m;++i,++p){ //构造所需要的过度根节点p->weight = 0;p->parent = 0;p->lchild = 0;p->rchild = 0;}//forfor(i=n+1;i<=m;++i){ //建立哈弗曼树int s1,s2;Select(HT,i-1,s1,s2);HT[s1].parent =i;HT[s2].parent =i;HT[i].lchild = s2;HT[i].rchild = s1;HT[i].weight = HT[s1].weight+HT[s2].weight;}//for//哈弗曼编码HC = (HuffmanCode)malloc((n+1)*sizeof(char *));char* cd = (char*)malloc(n*sizeof(char));cd[n-1] = '\0';for(i=1;i<=n;++i){int f;unsigned int c;int 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]);}//forfree(cd);}//HuffmanCoding//Y功能实现输出并保存字符串的二进制编码void CheckCoding(HuffmanTree HT, HuffmanCode HC, char *strcheck, int m,int k) { ofstream ofs("BCode.txt"); //查询哈弗曼编码信息int p;for(int i=0; i<m; i++){for(int j=1; HT[j].info != strcheck[i]; j++);cout<<HC[j]; //输出并保存字符串的二进制编码ofs<<HC[j];}cout<<endl;cout<<"字符串的二进制编码已经保存在“BCode.txt”中"<<endl;//cout<<"译码翻译得到的文章已保存在“Data.txt”中"<<endl;cout<<"************************************************************** *****************"<<endl;cout<<"各字符对应的编码为:"<<endl; //输出各字符对应的哈夫曼编码for( p=1;p<=k;p++){cout<<HT[p].info <<": "<<HC[p]<<endl;}}//CheckCoding//对键盘输入的二进制代码进行译码void HuffmanTranslateCoding(HuffmanTree HT, int n,char*c){ ofstream ofs("TransBData.txt"); //译码过程int m=2*n-1;int i,j=0;cout<<"译码翻译得到的文章已保存在“TransBData.txt”中"<<endl;cout<<"译码翻译得到的文章为:";while(c[j]!='\0'){i=m;while(HT[i].lchild && HT[i].rchild){if(c[j]=='0')i=HT[i].lchild;else if(c[j]=='1')i=HT[i].rchild;j++;}cout<<HT[i].info; //翻译成字符串并输出和保存ofs<<HT[i].info;}}//译码过程、、对"BCode.txt"的编码进行译码void HuffmanTranslateCoding2(HuffmanTree HT, int n){ ifstream ifs("BCode.txt");ofstream ofs("TransBData2.txt");string c;int m=2*n-1;int i,j=0;getline(ifs,c);cout<<"译码翻译得到的文章已保存在“TransBData2.txt”中"<<endl;cout<<"译码翻译得到的文章为:";while(c[j]!='\0'){i=m;while(HT[i].lchild && HT[i].rchild){if(c[j]=='0')i=HT[i].lchild;else if(c[j]=='1')i=HT[i].rchild;j++;}cout<<HT[i].info; //翻译成字符串并输出和保存ofs<<HT[i].info;}}void Menushow(){cout<<"||******************************************************************** ****||"<<endl;cout<<" || HuffmanCode and HUffmanTranslate System ||"<<endl;cout<<" || ***********哈夫曼编码/译码系统************* ||"<<endl;cout<<" || *************欢迎使用本系统**************** ||"<<endl;cout<<" || 东北电力大学信息工程学院计机093班兴趣小组||"<<endl;cout<<" || 制作人:范辉强(组长)李哲周兴宇||"<<endl;cout<<"||******************************************************************** ****||"<<endl;cout<<" ||在本系统中您可以进行如下操作:||"<<endl;cout<<" ||第一部分功能:||"<<endl;cout<<" || A :从文件提取字符串,然后对提取的字符串进行编码||"<<endl;cout<<" || B :根据W操作对“WCode.txt”里的二进制编码进行译码||"<<endl;cout<<" ||第二部分功能:||"<<endl;cout<<" || C :对您输入的字符串进行编码||"<<endl;cout<<" || D:对BCode.txt里的编码进行译码||"<<endl;cout<<" || E :对您输入的二进制编码进行译码||"<<endl;cout<<" ||第三部分功能:||"<<endl;cout<<" || F :退出本系统||"<<endl;cout<<"||******************************************************************** ****||"<<endl;cout<<" ||温馨提示:||"<<endl;cout<<" || 执行A,请将您的数据存储在同目录下名为“WData”文本文档里||"<<endl;cout<<" || 在执行C操作时务必在您输入的字符串后加上“#”||"<<endl;cout<<" || B与A是对应的B在A后运行||"<<endl;cout<<" || D/E与C是对应的,即B/C是根据C来进行译码的||"<<endl;cout<<" || 译码D/E应在编码C后才能进行||"<<endl;cout<<" ||*********************** Copyright by FanFan ********************||"<<endl;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///main().cppint main(){int n=0,i=0,k=0,j,h,*w;FILE *fp;char ch2,str[MAXDA TA],choose,name[]="BData.txt";w=new int[MAXSIZE];char *info;char *strcheck=str;info=new char[MAXSIZE];char *ch=new char[MAXSIZE];HuffmanTree HT=new HTNode[MAXSIZE];HuffmanCode HC=NULL;HuffmanTree1 HuffmanNode;Menushow();while(1){cout<<endl;cout<<"************************************************************** *****************"<<endl;cout<<"*********************************************************** ********************"<<endl;cout<<"请输入您要进行的操作(W/F/B/C/Y/T)(不区分大小写):"<<endl;cin>>choose;cout<<"************************************************************** *****************"<<endl;switch(choose){case 'A':case 'a':HuffmanNode.TranslatedCode();break;case 'B':case 'b':HuffmanNode.TranslateArtcle(HuffmanNode.hf,HuffmanNode.f);case 'D':case 'd':HuffmanTranslateCoding2( HT,n);break;case 'E':case 'e'://进行译码操作cout<<"请您输入您要编译的二进制编码: "<<endl;cin>>ch;HuffmanTranslateCoding(HT,n,ch);break;case 'T':case 't'://退出系统return 0;case 'C':case 'c'://进行编码操作cout<<"请输入您要编码的字符串:"<<endl;//从键盘输入字符串存放在字符数组str[1000]中/*if ((fp=fopen(name,"w"))==NULL){cout<<"cannot open file"<<endl;exit(0);}*/fp=fopen(name,"w");ch2=getchar();//接收上一次键盘输入的换行符ch2=getchar();while(ch2!='#'){fputc(ch2,fp);str[n++]=ch2;putchar(str[n-1]);ch2=getchar();}putchar(10);fclose(fp);cout<<endl;cout<<"输入的数据已经保存在“BData.txt”中"<<endl;cout<<"*******************************************************************************"<<endl;cout<<"字符串中共含有字符"<<n<<"个"<<endl;cout<<"*********************************************************** ********************"<<endl;for(i=0;i<n;i++) // 统计从键盘输入的字符串的信息{j=0;h=0;while(str[i]!=str[j])j++;if(j==i){info[k]=str[i];cout<<"字符"<<info[k]<<"出现";}elsecontinue;for(j=i;j<n;j++){if(str[i]==str[j])h++;}cout<<h<<"次"<<endl;w[k]=h;k++;}cout<<"************************************************************** *****************"<<endl;cout<<"字符串中字符种类有"<<k<<"种"<<endl;cout<<"************************************************************** *****************"<<endl;HuffmanCoding( HT, HC, w, n,info);//对输入的字符串进行编码*strcheck=str[0];cout<<"您输入的字符串编码为:"<<endl;CheckCoding(HT,HC,strcheck,n,k);break;default:cout<<"对不起,您的输入不正确!请重新输入"<<endl;}//switch}//while}//main程序清单.cpp#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string>#include"Hh1.h"using namespace std;FILE * f1=fopen("d:\\pra1.txt","r");FILE * f2=fopen("d:\\pra2.txt","w");FILE * f3=fopen("d:\\pra4.huf","w");int main(){init(SN); //初始化字符数据库// input(f1); //读入初始文件的字符//for(int i=0;forest[i]!=NULL;i++)cout<<forest[i]->c<<":"<<forest[i]->weight<<endl; //输出字符及出现次数// cout<<"出现字符种类"<<count<<endl; //输出字符种类//HFM huffman(count); //创建哈夫曼树实例// huffman.creat(); //创建哈夫曼树// count=0;huffman.hufcode(); //哈夫曼编码,此时为逆向//exchange(); //调整首尾对调哈夫曼编码// huffman.savewithhufcode(f1,f2); //用哈夫曼编码存储原文件//cout<<endl;cout<<"1.查看哈夫曼编码"<<endl;cout<<"2.哈夫曼解码"<<endl;cout<<"3.查看压缩率"<<endl;int choice;cin>>choice;while(choice>=1&&choice<=3){switch(choice){case 1:{for(i=0;hufNode[i].sig!=NULL;i++){cout<<"字符"<<hufNode[i].sig->c<<"的哈夫曼编码:"; //输出哈夫曼编码//for(int j=0;j<hufNode[i].size;j++)cout<<hufNode[i].code[j];cout<<endl;}cout<<"最大列数:"<<huffman.maxc()<<endl;break;}case 2:{fclose(f2);f2=fopen("d:\\pra2.txt","r");huffman.hufdecode(f2,f3); //哈夫曼解码//cout<<endl;break;}case 3:{compress(); //查看压缩情况//cout<<endl;}}cout<<"1.查看哈夫曼编码"<<endl;cout<<"2.哈夫曼解码"<<endl;cout<<"3.查看压缩率"<<endl;cin>>choice;}cout<<"*谢谢使用*"<<endl; //退出操作//return 0;}.h#include<iostream>using namespace std;struct signode{ //signode节点,哈夫曼树节点//char c; //字符//int weight; //权重//bool b; //文章中是否出现//。
Huffman编码与译码 代码

% 1 完成对输入的序列进行各个码元的概率统计;%完成对字符串中的各字符的统计,并列出其概率分布矩阵,返回pro矩阵%s:待编码序列,S:所含的码元序列function pro=getpro(s)pro=[];a=length(s);S=unique(s);b=length(S);c=zeros(1,b); %用以存放个序列中各个码元的个数;%/////////////////////////////////////////////%进行概率计算;for i=1:bfor j=1:aif S(i)==s(j)c(i)=c(i)+1;else continue;end;end;end;pro=c./a;disp(S);disp(pro);%完成对已知编码序列的译码,以及在改变码表中的某一位值得情况下,再一次译码,计算其误码率;%Codenumber:已编码序列;huffmantable:码表;Code2:各码元的码长;pro2:各码元的概率分布矩阵;%s:原始序列;decodenumber:译码序列;function decodenumber=huffmandecode(Codenumber,huffmantable,Code2,pro2,bit)mm=unique(bit); %码元序列mm=mm(pro2(2,:));[lx,ly]=size(huffmantable);LL=size(Codenumber,2);decodenumber=[];ZF=[Codenumber,-ones(1,max(Code2))];for j=1:length(bit)for i=1:lxk=Code2(i);while(ZF(1:k)==huffmantable(i,1:k))decodenumber=[decodenumber,mm(i)];ZF=ZF(k+1:end);endendenddisp('译码序列如下:');disp(decodenumber);disp('原始序列如下:');disp(bit);end %对于译码部分所用到的部分主要是编码时生成的码表以及huffmantree,在进行编码的时候,%通过筛选后的源字符串的字符序列的下标,与码表中的每行相对应的原则,遍历编码序列;%在遍历的时候,通过码表中各行的码长,控制遍历的长度,与每行中的码表进行比较,输出相对应的字符,即完成了译码。
赫夫曼树编码译码程序设计

《数据结构与算法》课程设计指导教师:班级:计算机科学与技术实验班学号:姓名:《数据结构与算法》课程设计目录一、前言1.摘要2.《数据结构与算法》课程设计任务书二、实验目的三、题目--赫夫曼编码/译码器1.问题描述2.基本要求3.测试要求4.实现提示四、需求分析--具体要求五、概要设计六、程序说明七、详细设计八、实验心得与体会前言1.摘要随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。
算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。
算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。
它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。
数据结构有逻辑上的数据结构和物理上的数据结构之分。
逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。
数据结构是数据存在的形式。
《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。
数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。
学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。
通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。
2.《数据结构与算法》课程设计任务书《数据结构与算法》是计算机专业重要的核心课程之一,在计算机专业的学习过程中占有非常重要的地位。
哈弗曼编码与译码

一个完整的系统应具有以下功能:(1) I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。
(2) E:编码(Encoding)。
利用已建好的赫夫曼树(如不在存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3) D:译码(Decoding)。
利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。
以下为选做:(4) P:印代码文件(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5) T:印赫夫曼树(Tree printing)。
将已在存中的赫夫曼树以直观的方式(比如树)显示在终端上,同时将此字符形式的赫夫曼树写入文件TreePrint 中。
2.测试要求(1) 已知某系统在通信联络中只可能出现八种字符,其频率分别为0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计赫夫曼编码。
(2) 用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:“THIS PROGRAME IS MY FAVORITE”。
3.实现提示(1) 编码结果以文本方式存储在文件Codefile中。
(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。
(3) 在程序的一次执行过程中,第一次执行I,D或C命令之后,赫夫曼树已经在存了,不必再读入。
每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。
#include <string.h>#include <stdio.h>#include <stdlib.h>#include <malloc.h>typedef struct {char letter;float 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}//forHT[s1].code=HT[s2].code=1;}//selectvoid 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].cod e=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);}//iffor(i=0;p[i]!='\0';i++){if(fwrite(p+i,sizeof(char),1,fp)!=1){//fwrite函数写数据块printf("File write error!\n");exit(0);}//if}//forfclose(fp);}//save//************************编码与译码操作********************************** void Decoding(HuffmanTree HT,hfmlist HL,char*size,int n)//这个函数是用来译码的 {int i,j,k;char p[130];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--;}}}//forif( p[j-1]=='0')size[k++]=HL[i].letter;else size[k++]=HL[i].letter;size[k]='\0';}//decodingvoid 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];}//forcoding[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");}}//forprintf("\n");}//Printvoid PreOrderTraverse(HuffmanTree HT,int k,FILE *fp){//先序遍历并打印树,结果存放于fp中,k为根结点的下标int i;for(i=1;i<=DEPTH-1;i++)fprintf(fp," ");for(;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].rchild!=0){DEPTH++;PreOrderTraverse(HT,HT[k].rchild,fp);DEPTH--;}if(HT[k].lchild==0&&HT[k].rchild==0)return;return;} //PreOrderTraversevoid 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));//存储字符与权值,线性表长30printf("\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 %f",&(HL+i)->letter, &(HL+i)->wt);getchar();}//forif((fp5=fopen("hfmTree.txt","w"))==NULL){printf("cannot open file!\n");exit(0);}//iffor(i=1;i<=n;i++){fprintf(fp5,"第%d个字符及权值:\t\t\t",i);fprintf(fp5,"%c %f\n",(HL+i)->letter,(HL+i)->wt);}//forfclose(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);}//ifcha=getchar();while(cha!='#'){fputc(cha,fp2);cha=getchar();}//whilegetchar();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("CodeFile.txt","w"))==NULL){printf("cannot open the file!\n");exit(0);}//ifif((fp4=fopen("CodeFile.txt","r"))==NULL){printf("cannot open the file!\n");exit(0);}//ifPrint(fp4,fp1);printf("该代码文件已经存在并命名为CodePrin.txt\n"); fclose(fp4);fclose(fp1);break;case 't':printf("打印树存在于文件TreePrin中\n");if((fp3=fopen("TreePrin.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;}//switchprintf("\n请选择操作(i,e,d,p,t,q):");ch=getchar();getchar();}while(ch!='q');//doreturn 0 ;}//main。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
int weight;
int lchild,rchild,parent;
}Htnode,*HuffmanTree; //哈弗曼树节点类型,动态分配数组存储哈弗曼树typedef char * * Huffmancode; //动态分配数组存储哈弗曼编码表
void bianma(Huffmancode ch,int n); //编码
void yima(Htnode *HT, int n); //译码
int createtree(Htnode *&HT, Huffmancode &HC,int *weight,int n); //构建哈弗曼树void select(Htnode *HT,int n,int *s1,int *s2); //求节点中两个最小数
/*----------main 函数----------*/
int main (void)
{
Htnode *HT;
int n=4,a; //叶子节点4个
int weight[5]={18,7,5,2,4}; //weight[0]为权值之和
char ch[4]={'A','B','C','D'},c;
char **HC;
createtree(HT, HC,weight, n);
while(a!=0){ //a=0时退出,so是按0键退出,或者改成a!=3
printf("***编码请按1,译码请按2,退出请按0***");
printf("请输入您的选择:\n");
scanf("%d%c",&a,&c);
switch(a){
case 1: bianma(HC,n); break;
case 2: yima(HT,2*n); break;
case 0: break;
default:printf("输入错误!");break;
}
}
return 0;
}
/*----------构建哈弗曼树---------- */
int createtree(Htnode *&HT, Huffmancode &HC,int *weight,int n)
{
int m,i ,start,s1,s2,c,f;
char *cd;
if(n<=1)
return 0;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(Htnode)); //0号单元未用,动态分配内存
for(i=0;i<=n;i++){ //n个节点权值初始化
HT[i].weight=weight[i];
}
for(i=0;i<=m;i++){ //m个节点双亲,左右孩子初始化
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for(i=n+1;i<=m;i++){
select(HT,i-1,&s1,&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;
}
/*从叶子到根逆向求每个字符的编码*/
HC=(Huffmancode)malloc((n+1)*sizeof(char*)); //分配n个字符编码的头指针向量
cd=(char *)malloc(n*sizeof(char)); //分配求编码的工作空间
cd[n-1]='\0';
for (i=1; i<=n; i++){ //从叶子到根计算第n个叶子结点的编码start=n-1; //编码结束符位置
for(c=i, f=HT[i].parent ; f!=0 ; c=f, f=HT[f].parent){ //到最后只有根的父节点是0 if(HT[f].lchild==c) cd[--start]='0';
else cd[--start]='1'; //存储时编码顺序还是正着的
}
HC[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个字符编码分配空间
strcpy(HC[i],&cd[start]); //从cd复制编码到HC
}
free(cd);
return 1;
}
/*----------编码----------*/
void bianma(Huffmancode ch,int n)
{
char c[52];
int i;
printf("请输入一个字符串(输入的字符个数少于50):\n");
gets(c);
for( i=0; c[i]!='\0'; i++){
if(c[i]<'A'||c[i]>'D')
continue;
printf("%s",ch[c[i]-64]);
}
printf("\n");
}
/*----------译码----------*/
void yima(Htnode *HT, int n)
{
char c[102];
int i,a;
printf("请输入一个01字符串(字符个数少于100个):\n");
gets(c);
for( i=0; c[i]!='\0';){
for( a=n-1; HT[a].lchild!=0 && c[i]!='\0';i++ ){ //每次查找一个字母a都要从n-1开始,
if(c[i]!='0'&&c[i]!='1') //并且从上次01字符结束的地方开始
continue ;
else{
if(c[i] =='1') a=HT[a].rchild;
else
a=HT[a].lchild;
}
}
if(a<=n/2)
printf("%c",'A'+a-1);
else{
printf("出现错误\n");
break;
}
}
printf("\n");
}
/*----------求节点中两个最小数----------*/
void select(Htnode *HT,int n,int *s1,int *s2)
{
int i,min1=18,min2=18;
min1=HT[0].weight;
for(i=1;i<=n;i++){
if(HT[i].parent==0){
if(HT[i].weight<min1)
{
min1=HT[i].weight;
*s1=i;
continue;
}
if(HT[i].weight<min2){
min2=HT[i].weight;
*s2=i;
}
}
}
for(i=1;i<=n;i++){
if(HT[i].parent==0&&HT[i].weight<min2&&HT[i].weight>=min1&&*s1!=i){ min2=HT[i].weight;
*s2=i;
}
}
}。