哈夫曼编译码器 c语言

合集下载

完整word版哈夫曼编码译码器数据结构C语言模板

完整word版哈夫曼编码译码器数据结构C语言模板

一、需求分析目前,进行快速远距离通信的主要手段是电报,即将需传送的文字转化成由二级制的字符组成种字符,只需两个字符的串,便可”,它只有4的字符串。

例如,假设需传送的电文为“ABACCDA,00010010101100”则上述和11,7个字符的电文便为“以分辨。

假设A、B、C、D、的编码分别为00,01,10 14位,对方接受时,可按二位一分进行译码。

总长当然,在传送电文时,希望总长尽可能地短。

如果对每个字符设计长度不等的编码,且让电文DC、中出现次数较多的字符采用尽可能短的编码,则传送电文的总长便可减少。

如果设计A、B、。

但是,000011010”,则上述7个字符的电文可转换成总长为9的字符串“的编码分别为0,00,1,01”就可以有很多种译法,0000个字符的字串“这样的电文无法翻译,例如传送过去的字符串中前4”等。

因此,若要设计长短不等的编码,则必须是任一字ABAAAAA”或者“BB”,或者“或是“符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。

然而,如何进行前缀编码就是利用哈夫曼树来做,也就有了现在的哈夫曼编码和译码。

二、概要设计译码利用哈夫曼树编/ 、建立哈夫曼树(一)、对哈夫曼树进行编码(二)、输出对应字符的编码(三)、译码过程(四)主要代码实现://结构体的定义struct code{char a;int w;int parent;int lchild;int rchild;};void creation(code *p,int n,int m); //建立哈夫曼树//编码void coding(code *p,int n);//输出函数void display(code *p,int n,int m);//译码void translate(char **hc,code *p,int n);详细设计三、(一)、建立哈夫曼树10序号:5 3 4 2 7 6 1* * *c *字符:db a 4 6 6 权值:10 6 4 2 3 3 1 d **33333 c*c * * 1 2 2 1 2 1 abb a 3-3图3-1 图b a 3-2 图1(二)、对哈夫曼树进行编码主要代码实现:从叶子到根逆向求编码for(c=i,f=p[i].parent;f!=0;c=f,f=p[f].parent){*'0'//左孩子编码为if(p[f].lchild==c) 1 { d* cd[--start]='0'; 0 1} c* 1 0 '1'else //右孩子编码为{ bacd[--start]='1';3-4图}}(三)、输出对应字符的码编码字符110 a111 b10 c3-1表d(四)、译码过程主要代码实现:0 比较两个字符串是否相等,相等则输出if(strcmp(a,hc[i])==0) //{或'1'确定找左孩子或右孩子//从根出发,按字符'0' for(c=2*n-1,j=0;a[j]!='\0';j++){if(a[j]=='0') //左孩子从跟到叶子顺向求字符{*c=p[c].lchild;1 0}d * else 1 0{c *右孩子c=p[c].rchild; // 1 0}ba }3-5 图2调试分析四、、数字的输入判断(一)4-1 图、字母的输入判断(二)4-2 图(三)、程序是否继续进行的判断4-3 图用户手册五、;提示输(一)、首先根据提示输入初始化数据,提示输入一个数字,请输入一个数a,0<a<9999中的一个字符;请勿在输入一个数字后再输入一个入一个字母,则请输入一个字母(a~z)或者(A~Z) 字符,或者在输入一个字符后再输入一个数字。

哈夫曼编码译码C语言编写

哈夫曼编码译码C语言编写

哈夫曼编码译码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语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言⒈简介本文档旨在介绍一个使用C语言实现的哈夫曼编码译码器的数据结构。

哈夫曼编码是一种用于数据压缩的算法,它通过将频率较高的字符用较短的编码表示,从而实现数据的压缩和解压缩。

⒉哈夫曼编码(Huffman Coding)基本概念⑴字符频率统计在进行哈夫曼编码之前,我们首先需要统计每个字符在待编码的数据中出现的频率。

通过遍历数据,记录每个字符的出现次数,我们可以得到一个字符频率的统计表。

⑵构建哈夫曼树通过字符频率的统计表,我们可以构建一个哈夫曼树。

哈夫曼树是一种二叉树,其中每个叶节点表示一个字符,而每个内部节点表示一个权重,即两个子节点的频率之和。

⑶哈夫曼编码在哈夫曼树构建完成后,我们可以根据树的结构每个字符的编码。

哈夫曼编码的特点是没有任何一个字符的编码是另一个字符编码的前缀,这种编码方式称为前缀编码。

⑷哈夫曼译码根据字符的哈夫曼编码,我们可以将编码后的数据进行解码,还原为原始的数据。

通过遍历哈夫曼树,从根节点开始,根据每个二进制位的取值进行向左或向右的移动,直至叶节点,然后获取该叶节点对应的字符。

⒊数据结构设计⑴结点结构定义一个哈夫曼树的结点结构,包含以下字段:●`char data`:字符●`int frequency`:字符的频率●`int is_leaf`:是否为叶节点●`struct Node left_child`:左子节点●`struct Node right_child`:右子节点⑵频率统计表使用一个数组或链表来记录每个字符的频率统计信息,包含以下字段:●`char data`:字符●`int frequency`:字符的频率⑶编码表使用一个数组或链表来记录每个字符的哈夫曼编码,包含以下字段:●`char data`:字符●`char code`:编码⒋算法流程⑴字符频率统计算法步骤:⒈初始化频率统计表为空。

⒉读取待编码的数据。

哈夫曼码编、译码器的实现

哈夫曼码编、译码器的实现

根据下面给出的存储结构定义 typedef struct // 定义哈夫曼树中每个结点结构体类型 { char ch; //结点字符信息 int weight; // 定义一个整型权值变量 int lchild; // 定义左、右孩子及双亲指针 int rchild; int parent; } HTNode; typedef HTNode HFMT[MAXLEN]; //用户自定义HFMT数组类型 typedef char** HfCode;//动态分配字符数组存储哈夫曼编码表 (7)基本操作的函数设计 void InitHFMT(HFMT T);//初始化哈夫曼树 void InputWeight(HFMT T,char* weightFile);// 输入权值 void SelectMin(HFMT T,int i,int *p1,int *p2); //选择所有结点中较小的结点 void CreatHFMT(HFMT T);// 构造哈夫曼树,T[2*n-1]为其根结点 void PrintHFMT (HFMT T);// 输出向量状态表 void printHfCode(HfCode hc);//输出字符的哈夫曼编码序列 HfCode hfEnCoding(HFMT T);//利用构成的哈夫曼树生成字符的编码 void print_HuffmanTree(HFMT HT,int t,int i)//按树形形态输出哈 夫曼树的形态 void Encoder(char* original,char* codeFile,HfCode hc,HFMT HT); //利用已建好的哈夫曼树,对original文件中要传输的原始数据进行编 码, //将编码结果存入文件codeFile中 void Decoder(char* codeFile ,char* textFile,HFMT HT); //利用已建好的哈夫曼树,对传输到达的codeFile中的数据代码进行译

哈夫曼编码译码器

哈夫曼编码译码器
cin>>Choose;
if(Choose=='2') { //键盘输入建立哈夫曼树
CreateHuffmanTreeFromKeyboard();
}//choose=='2'
else { //从哈夫曼树文件hfmTree.dat中读入信息并建立哈夫曼树
CreateHuffmanTreeFromFile();
pos1=k;
}
else
if(Node[k].weight<max2){ //发现比当前次大值还大的次大权重
max2=Node[k].weight;
pos2=k;
for(int i=0;i<Num;i++) {//读入哈夫曼树的叶子结点信息
cout<<"请输入第"<<i+1<<"个字符值";
getchar();
Node[i].sourcecode=getchar(); //源文的字符存入字符数组Info[]
return;
}
fop.write((char*)&Num,sizeof(Num)); //先写入哈夫曼树的叶子结点个数
for(int n=0;n<2*Num-1;n++) { //最后写入哈夫曼树的各个结点(存储在Node[]中)
fop.write((char*)&Node[n],sizeof(Node[n]));
//产生所有叶子结点中字符的编码
for (int m=0;m<Num;m++) {
//产生Node[i].sourcecode的编码,存入Node[i].code中

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)哈夫曼编码是一种常见的前缀编码方式,被广泛应用于数据压缩和传输中。

它是由大卫·哈夫曼(David A. Huffman)于1952年提出的,用于通过将不同的字符映射到不同长度的二进制码来实现数据的高效编码和解码。

1.统计字符频率:遍历待编码的文本,记录每个字符出现的频率。

2.构建哈夫曼树:根据字符频率构建哈夫曼树,其中出现频率越高的字符位于树的较低层,频率越低的字符位于树的较高层。

3.生成编码表:从哈夫曼树的根节点开始,遍历哈夫曼树的每个节点,为每个字符生成对应的编码。

在遍历过程中,从根节点到叶子节点的路径上的“0”表示向左,路径上的“1”表示向右。

4.进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。

5.进行解码:根据生成的编码表和编码结果,将编码替换为原始字符。

下面是一个用C语言实现的简单哈夫曼编码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>//定义哈夫曼树的节点结构体typedef struct HuffmanNodechar data; // 字符数据int freq; // 字符出现的频率struct HuffmanNode *left; // 左子节点struct HuffmanNode *right; // 右子节点} HuffmanNode;//定义编码表typedef structchar data; // 字符数据char *code; // 字符对应的编码} HuffmanCode;//统计字符频率int *countFrequency(char *text)int *frequency = (int *)calloc(256, sizeof(int)); int len = strlen(text);for (int i = 0; i < len; i++)frequency[(int)text[i]]++;}return frequency;//创建哈夫曼树HuffmanNode *createHuffmanTree(int *frequency)//初始化叶子节点HuffmanNode **leaves = (HuffmanNode **)malloc(256 * sizeof(HuffmanNode *));for (int i = 0; i < 256; i++)if (frequency[i] > 0)HuffmanNode *leaf = (HuffmanNode*)malloc(sizeof(HuffmanNode));leaf->data = (char)i;leaf->freq = frequency[i];leaf->left = NULL;leaf->right = NULL;leaves[i] = leaf;} elseleaves[i] = NULL;}}//构建哈夫曼树while (1)int min1 = -1, min2 = -1;for (int i = 0; i < 256; i++)if (leaves[i] != NULL)if (min1 == -1 , leaves[i]->freq < leaves[min1]->freq) min2 = min1;min1 = i;} else if (min2 == -1 , leaves[i]->freq < leaves[min2]->freq)min2 = i;}}}if (min2 == -1)break;}HuffmanNode *parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));parent->data = 0;parent->freq = leaves[min1]->freq + leaves[min2]->freq;parent->left = leaves[min1];parent->right = leaves[min2];leaves[min1] = parent;leaves[min2] = NULL;}HuffmanNode *root = leaves[min1];free(leaves);return root;//生成编码表void generateHuffmanCode(HuffmanNode *root, HuffmanCode *huffmanCode, char *code, int depth)if (root->left == NULL && root->right == NULL)code[depth] = '\0';huffmanCode[root->data].data = root->data;huffmanCode[root->data].code = strdup(code);return;}if (root->left != NULL)code[depth] = '0';generateHuffmanCode(root->left, huffmanCode, code, depth + 1);}if (root->right != NULL)code[depth] = '1';generateHuffmanCode(root->right, huffmanCode, code, depth + 1);}//进行编码char *encodeText(char *text, HuffmanCode *huffmanCode)int len = strlen(text);int codeLen = 0;char *code = (char *)malloc(len * 8 * sizeof(char));for (int i = 0; i < len; i++)strcat(code + codeLen, huffmanCode[(int)text[i]].code);codeLen += strlen(huffmanCode[(int)text[i]].code);}return code;//进行解码char* decodeText(char* code, HuffmanNode* root) int len = strlen(code);char* text = (char*)malloc(len * sizeof(char)); int textLen = 0;HuffmanNode* node = root;for (int i = 0; i < len; i++)if (code[i] == '0')node = node->left;} elsenode = node->right;}if (node->left == NULL && node->right == NULL) text[textLen] = node->data;textLen++;node = root;}}text[textLen] = '\0';return text;int maichar *text = "Hello, World!";int *frequency = countFrequency(text);HuffmanNode *root = createHuffmanTree(frequency);HuffmanCode *huffmanCode = (HuffmanCode *)malloc(256 * sizeof(HuffmanCode));char code[256];generateHuffmanCode(root, huffmanCode, code, 0);char *encodedText = encodeText(text, huffmanCode);char *decodedText = decodeText(encodedText, root);printf("Original Text: %s\n", text);printf("Encoded Text: %s\n", encodedText);printf("Decoded Text: %s\n", decodedText);//释放内存free(frequency);free(root);for (int i = 0; i < 256; i++)if (huffmanCode[i].code != NULL)free(huffmanCode[i].code);}}free(huffmanCode);free(encodedText);free(decodedText);return 0;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。

哈夫曼编码译码器

哈夫曼编码译码器

哈夫曼编码译码器#include<stdio.h> #include<conio.h> #include<malloc.h> #include<string.h> #include<stdlib.h>#define ERROR 0; #define OK 1;typedef int Status;typedef struct{ unsigned int weight; int key;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char * * HuffmanCode;int **KEY;int N;Status GetData(){ FILE *fp;int key[100][2]; int ch,k,i,tem; char str[16];fp=fopen("data.txt","r");k=0;while(!feof(fp)){ch=fgetc(fp);i=0;while(ch!=' '){ str[i]=ch;i++;ch=fgetc(fp);}str[i]='\0';//printf("%d\n",strcmp(str," 空格"));if(!strcmp(str," 空格")){key[k][0]=' ';}else{ key[k][0]=str[0];}ch=fgetc(fp);tem=0;while(ch!='\n'&&ch!=EOF){ tem=tem*10+ch-'0'; ch=fgetc(fp); } key[k][1]=tem; //printf("%c,%d\n",key[k][0],key[k][1]);k++;}KEY=(int * *)malloc(k*sizeof(int *));if(!KEY){return ERROR;}for(i=0;i<k;i++){KEY[i]=(int*)malloc(2*sizeof(int));if(!KEY[i]){return ERROR;KEY[i][0]=key[i][0]; KEY[i][1]=key[i][1]; }N=k; fclose(fp); return OK;}Status InitHuffmanTree(HuffmanTree &HT){int i;HT=(HTNode *)malloc((2*N-1)*sizeof(HTNode)); if(!HT){ return ERROR;} for(i=0;i<N;i++){HT[i].weight=KEY[i][1]; HT[i].key=KEY[i][0]; HT[i].parent=-1; HT[i].lchild=-1;HT[i].rchild=-1;} for(;i<2*N-1;i++){HT[i].parent=-1;} return OK;}void Select(HuffmanTree &HT,int n,int &fi,int &si){ int i=0,tem; if(n>=2){while(((HT+i)->parent)!=-1){ i++;}fi=i;i++;while((HT+i)->parent!=-1){ i++;}si=i;if((HT+fi)->weight>(HT+si)->weight){ tem=fi;fi=si;si=tem;}for(i++;i<n;i++){if((HT+i)->parent==-1){ if((HT+i)->weight<(HT+fi)->weight){ si=fi; fi=i;}else{if((HT+i)->weight<(HT+si)->weight){ si=i;}}}int HuffmanTreeAllReady(HuffmanTree HT,int m){int sum=0,i;for(i=0;i<m;i++){ if((HT+i)->parent==-1){ sum++;}if(sum>1){return 0;}}return 1;}void CreateHuffmanTree(HuffmanTree &HT,int n){int s1,s2;while(!HuffmanTreeAllReady(HT,n)){ Select(HT,n,s1,s2);HT[n].parent=-1;HT[n].lchild=s1;HT[n].rchild=s2;HT[n].weight=HT[s1].weight+HT[s2].weight; HT[s1].parent=n; HT[s2].parent=n;n++;}void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n){ char * str;int len=0,tem,i,j;unsigned int p;str=(char *)malloc(n*sizeof(char));for(i=0;i<n;i++){p=i;len=0;while((tem=HT[p].parent)!=-1){ if(HT[tem].lchild==p){ str[len]='0'; }else{str[len]='1';}len++;p=tem;}HC[i]=(char *)malloc((len+1)*sizeof(char));if(HC[i]){for(j=0;j<len;j++){HC[i][j]=str[len-1-j];H c ==_e n lr /ss s e n H /s—p 「Hf(=%a%2n=HC==0L_en)JvoidoufpufHuffmancodeIuffmancodeHe)宀5'二f o 「T o x N T +)宀 p 「imf(=%c.VvoidcodingTuffmancodeHe)宀F_LE-4P Winf ch J八f p H f o p e n v &a s H .x f ==3八 fqHfopenv&®®H .b d ==w +=)八 chHfgeo(fp)八wh=e(ch一 HEOF)宀i f o h H H :)宀110 八e-se 宀ll c h 」A 匚一八1p 「Hf(=%c=chxuprimf(=%s=HCs- c h -l g e o (f p )-fcose(fp)八fcose(fq)八prinmoK云)voidDecoding(HuffmanTreeHTjnfN)宀F_LE-4P Winfch J八fqHfopenv ^a s H .x f ==w +=)八 fpHfopenv孺chHfgeo(fp)八wh=e(ch 一 HEOF)宀ll 2*N 2w h =e (H T s _c h i _d H ±QO QO H T s 「c h i _d H ±)宀i f o h H H O )宀ll H T s o h 云e-se 宀llH T s 「c h i _a—prinff(=%c=ch)八 chHfgeo(fp)八//printf("%c",ch); fputc(HT[t].key,fq); //printf("%c",HT[t].key);//printf("%s",HC[t]); //ch=fgetc(fp);}fclose(fp);fclose(fq);printf("OK\n");}int main(){HuffmanTree HT;HuffmanCode HC;int n,i,j,a,b,x;GetData();HC=(char * *)malloc((N)*sizeof(char *));InitHuffmanTree(HT);CreateHuffmanTree(HT,N);HuffmanCoding(HT,HC,N); //for(i=0;i<2*N-1;i++){ //printf("%d,%d,%d,%c,%d,%d\n",i,HT[i].parent,HT[i].weight,HT[i].key,H T[i].lchild,HT[i].rchild);//}printf(" 选项:1. 输出哈夫曼编码2. 输入明文得到密文3. 输入密文得到明文0. 退出\n");printf(" 输入选项:");while(scanf("%d",&x),x){ switch(x){case 1 :{OutputHuffmanCode(HC); break;}case 2 :{Coding(HC);}case 3 :{Decoding(HT,N);}}printf(" 输入: 1. 输出哈夫曼编码2. 输入明文得到密文3. 输入密文得到明文0.退出\n");printf(" 输入选项:");}return 0;。

(完整word版)C语言哈夫曼编码、译码器

(完整word版)C语言哈夫曼编码、译码器

#include <iostream.h>#include <iomanip.h>#include <string.h>#include <malloc.h>#include <stdio.h>//typedef int TElemType;const int UINT_MAX = 1000;typedef struct{int weight;int parent, lchild, rchild;} HTNode, *HuffmanTree;typedef char **HuffmanCode;//-----------全局变量-----------------------HuffmanTree HT;HuffmanCode HC;int *w, i, j, n;char *z;int flag = 0;int numb = 0;// -----------------求赫夫曼编码-----------------------int min(HuffmanTree t, int i){// 函数void select()调用int j, flag;int k = UINT_MAX; // 取k为不小于可能的值for (j = 1; j <= i; j++)if (t[j].weight < k && t[j].parent == 0)k = t[j].weight, flag = j;t[flag].parent = 1;return flag;}//--------------------slect函数----------------------void select(HuffmanTree t, int i, int &s1, int &s2){// s1为最小的两个值中序号小的那个int j;s1 = min(t, i);s2 = min(t, i);if (s1 > s2){j = s1;s1 = s2;s2 = j;}}// --------------算法6.12--------------------------void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){// w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC int m, i, s1, s2, start;//unsigned c,f;int c, f;HuffmanTree p;char *cd;if (n <= 1)return ;//检测结点数是否可以构成树m = 2 * n - 1;HT = (HuffmanTree)malloc((m + 1) *sizeof(HTNode)); // 0号单元未用for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w){p->weight = *w;p->parent = 0;p->lchild = 0;p->rchild = 0;}for (; i <= m; ++i, ++p)p->parent = 0;for (i = n + 1; i <= m; ++i)// 建赫夫曼树{// 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 select(HT, i - 1, s1, s2);HT[s1].parent = 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个字符编码的头指针向量([0]不用)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';elsecd[--start] = '1';HC[i] = (char*)malloc((n - start) *sizeof(char));// 为第i个字符编码分配空间strcpy(HC[i], &cd[start]); // 从cd复制编码(串)到HC}free(cd); // 释放工作空间}//--------------初始化赫夫曼链表---------------------------------void Initialization(){flag = 1;int num;int num2;cout << "下面初始化赫夫曼链表" << endl << "数请输入结点的个n:";cin >> num;n = num;w = (int*)malloc(n *sizeof(int));z = (char*)malloc(n *sizeof(char));cout << "\n请依次输入" << n << "个字符(字符型)\n注意:必须以回车结束:" << endl;char base[2];for (i = 0; i < n; i++){cout << "第" << i + 1 << "个字符:" << endl;gets(base);*(z + i) = *base;for (i = 0; i <= n - 1; i++){cout << setw(6) << *(z + i);}cout << "\n请依次输入" << n << "个权值(\n注意:必须以回车结束):" << endl; for (i = 0; i <= n - 1; i++){cout << endl << "第" << i + 1 << "个字符的权值:";cin >> num2;*(w + i) = num2;}HuffmanCoding(HT, HC, w, n);//------------------------打印编码-------------------------------------------cout << "字符对应的编码为:" << endl;for (i = 1; i <= n; i++){//cout<<"字符"<<*(z+i-1)<<"的编码";puts(HC[i]);}//--------------------------将赫夫曼编码写入文件------------------------cout << "下面将赫夫曼编码写入文件" << endl << "...................." << endl; FILE *htmTree;char r[] =' ', '\0'};if ((htmTree = fopen("htmTree.txt", "w")) == NULL){cout << "can not open file" << endl;return ;}fputs(z, htmTree);for (i = 0; i < n + 1; i++){fprintf(htmTree, "%6d", *(w + i));fputs(r, htmTree);}for (i = 1; i <= n; i++){fputs(HC[i], htmTree);fputs(r, htmTree);}fclose(htmTree);cout << "已将字符与对应编码写入根目录下文件htmTree.txt中" << endl << endl; }//---------------------获取报文并写入文件---------------------------------void InputCode()//cout<<"请输入你想要编码的字符"<<endl;FILE *tobetran;char str[100];if ((tobetran = fopen("tobetran.txt", "w")) == NULL){cout << "不能打开文件" << endl;return ;}cout << "请输入你想要编码的字符" << endl;gets(str);fputs(str, tobetran);cout << "获取报文成功" << endl;fclose(tobetran);}//---------------------编码函数---------------------------------void Encoding(){cout << "下面对目录下文件tobetran.txt中的字符进行编码" << endl; FILE *tobetran, *codefile;if ((tobetran = fopen("tobetran.txt", "rb")) == NULL){cout << "不能打开文件" << endl;}if ((codefile = fopen("codefile.txt", "wb")) == NULL) {cout << "不能打开文件" << endl;}char *tran;i = 99;tran = (char*)malloc(100 *sizeof(char));while (i == 99){if (fgets(tran, 100, tobetran) == NULL){cout << "不能打开文件" << endl;break;}for (i = 0; *(tran + i) != '\0'; i++){for (j = 0; j <= n; j++){if (*(z + j - 1) == *(tran + i)){fputs(HC[j], codefile);if (j > n){cout << "字符错误,无法编码!" << endl;break;}}}}}cout << "编码工作完成" << endl << "编码写入目录下的codefile.txt中" << endl << endl;fclose(tobetran);fclose(codefile);free(tran);}//-----------------译码函数---------------------------------void Decoding(){cout << "下面对根目录下文件codefile.txt中的字符进行译码" << endl;FILE *codef, *txtfile;if ((txtfile = fopen("Textfile.txt", "w")) == NULL){cout << "不能打开文件" << endl;}//txtfile=fopen("Textfile.txt","w");if ((codef = fopen("codefile.txt", "r")) == NULL){cout << "不能打开文件" << endl;}//codef=fopen("codefile.txt","r");char *work, *work2, i2;int i4 = 0, i, i3;unsigned long length = 10000;work = (char*)malloc(length *sizeof(char)); fgets(work, length, codef);work2 = (char*)malloc(length *sizeof(char)); i3 = 2 * n - 1;for (i = 0; *(work + i - 1) != '\0'; i++){i2 = *(work + i);if (HT[i3].lchild == 0){*(work2 + i4) = *(z + i3 - 1);i4++;i3 = 2 * n - 1;i--;}else if (i2 == '0')i3 = HT[i3].lchild;i3 = HT[i3].rchild;}*(work2 + i4) = '\0';fputs(work2, txtfile);cout << "译码完成" << endl << "内容写入根目录下的文件txtfile.txt中" << endl << endl;cout << work2;free(work);free(work2);fclose(txtfile);fclose(codef);}//------------------------打印赫夫曼树的函数-----------------------void coprint(HuffmanTree start, HuffmanTree HT){if (start != HT){FILE *TreePrint;if ((TreePrint = fopen("TreePrint.txt", "a")) == NULL){cout << "创建文件失败" << endl;return ;numb++; //该变量为已被声明为全局变量coprint(HT + start->rchild, HT);cout << setw(5 *numb) << start->weight << endl;fprintf(TreePrint, "%d\n", start->weight);coprint(HT + start->lchild, HT);numb--;fclose(TreePrint);}}void Tree_printing(HuffmanTree HT, int w){HuffmanTree p;p = HT + w;cout << "下面打印赫夫曼树" << endl;coprint(p, HT);cout << "打印工作结束" << endl;}//------------------------主函数------------------------------------void main(){char choice;cout << " 赫夫曼编码解码系统" << endl;cout << "1.要初始化赫夫曼链表请输入'i'" << endl;cout << "2.要编码请输入'e'" << endl;cout << "3.要译码请输入'd'" << endl;cout << "4.要打印编码请输入'p'" << endl;cout << "5.要打印赫夫曼树请输入't'" << endl;cout << "6.要离开请输入'q'" << endl;// if(flag==0)cout<<"\n请先初始化赫夫曼链表,输入'i'"<<endl; cin >> choice;switch (choice){case 'i':Initialization();break;case 'w':InputCode();break;case 'e':Encoding();break;Decoding();break;case 't':Tree_printing(HT, 2 *n - 1);break;case 'q':default:cout << "input error" << endl;}}free(z);free(w);free(HT);}运行结果:赫夫曼编码解码系统1.要初始化赫夫曼链表请输入'i'2.要编码请输入'e'3.要译码请输入'd'4.要打印编码请输入'p'5.要打印赫夫曼树请输入't'6.要离开请输入'q'下面初始化赫夫曼链表数请输入结点的个n:8请依次输入8个字符(字符型)注意:必须以回车结束:第1个字符:a第2个字符:b第3个字符:c第4个字符:d第5个字符:e第6个字符:f第7个字符:g第8个字符:ha b c d e f g h 请依次输入8个权值(注意:必须以回车结束):第1个字符的权值:5第2个字符的权值:29第3个字符的权值:7第4个字符的权值:8第5个字符的权值:14第6个字符的权值:23第7个字符的权值:3第8个字符的权值:11字符对应的编码为:01101011101111110000111010下面将赫夫曼编码写入文件....................已将字符与对应编码写入根目录下文件htmTree.txt中赫夫曼编码解码系统1.要初始化赫夫曼链表请输入'i'2.要编码请输入'e'3.要译码请输入'd'4.要打印编码请输入'p'5.要打印赫夫曼树请输入't'6.要离开请输入'q'i下面初始化赫夫曼链表数请输入结点的个n:27请依次输入27个字符(字符型)注意:必须以回车结束:第1个字符:第2个字符:a第3个字符:b第4个字符:c第5个字符:d第6个字符:第7个字符: f第8个字符: g第9个字符: h第10个字符: i第11个字符: j第12个字符: k第13个字符: l第14个字符: m第15个字符: n第16个字符: o第17个字符: p第19个字符:r第20个字符:s第21个字符:t第22个字符:u第23个字符:v第24个字符:w第25个字符:x第26个字符:y第27个字符:za b c d e f gm n o p q r s t z请依次输入27个权值(第1个字符的权值:186第2个字符的权值:64第3个字符的权值:13第4个字符的权值:22第5个字符的权值:32第6个字符的权值:103第7个字符的权值:21第8个字符的权值:15第9个字符的权值:47第10个字符的权值:57第11个字符的权值:1第12个字符的权值:5第13个字符的权值:32第14个字符的权值:20第15个字符的权值:57第16个字符的权值:63第17个字符的权值:15第18个字符的权值:1第19个字符的权值:48第20个字符的权值:51第21个字符的权值:80第22个字符的权值:23第23个字符的权值:8第24个字符的权值:18第25个字符的权值:1第26个字符的权值:16第27个字符的权值:1字符对应的编码为: 11010101001000001010110010111110100101000001101111011100111101101011111111101111000100110111101110100100011111000011111101011110011110111101001111111011111下面将赫夫曼编码写入文件....................已将字符与对应编码写入根目录下文件htmTree.txt中。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言文档1.引言本文档介绍了一个基于哈夫曼编码的译码器的设计和实现。

哈夫曼编码是一种无损压缩算法,通过对出现频率较高的符号进行较短的编码,来减小数据的存储或传输所需的空间。

2.哈夫曼编码原理在哈夫曼编码中,使用一颗二叉树,将出现频率较高的符号表示为树的较浅的节点,而出现频率较低的符号表示为树的较深的节点。

通过遍历整个二叉树,可以得到每个符号对应的哈夫曼编码。

2.1 创建哈夫曼树首先,根据每个符号的出现频率,创建一颗包含所有符号的节点的最小堆。

然后,根据最小堆的特性,每次从最小堆中选取两个出现频率最低的节点,并合并为一个新节点。

重复这个过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。

2.2 哈夫曼编码通过遍历哈夫曼树,可以得到每个符号对应的哈夫曼编码。

在遍历的过程中,左孩子表示编码中的“0”,右孩子表示编码中的“1”。

每次左移一个位,表示向左遍历,每次右移一个位,表示向右遍历。

3.数据结构设计下面介绍了本文档中所使用的各种数据结构和相关函数的设计。

3.1 结构定义```cstruct Node {char symbol。

int frequency。

struct Node leftChild。

struct Node rightChild。

}。

```3.2 方法定义```c// 创建哈夫曼树struct Node createHuffmanTree(char symbols, int frequencies, int size)// 哈夫曼编码表void generateHuffmanTable(struct Node root, char huffmanTable, char currentCode)// 哈夫曼编码char encode(char data, char huffmanTable)// 哈夫曼译码char decode(char encodedData, struct Node root)```4.实现细节在这个章节中,我们将会具体讨论各个方法的实现细节和使用示例。

C语言—哈夫曼树编码器和译码器

C语言—哈夫曼树编码器和译码器

C语言—哈夫曼树编码器和译码器#include <stdio.h>#include "stdlib.h"#define MAXBIT 10#define MAXVALUE 10000#define MAXLEAF 100#define MAXNODE MAXLEAF*2-1//定义哈夫曼树编码类型typedef struct {char bit[MAXBIT]; //存放叶子结点字符编码过后的二进制编码int start; //存放叶子结点二进制编码在bit[]数组里的起始数组位置int length; //存放二进制编码的位数}HFMCode;//定义哈夫曼树结点类型typedef struct {char data; //编码字符int weight; //哈夫曼树结点的权值int parent; //哈夫曼树结点的父结点int lchild; //哈夫曼树结点的左孩子int rchild; //哈夫曼树结点的右孩子}HFMNode;//构造哈夫曼树void createHFMTree(HFMNode hfmnode[MAXNODE],int n){int i,j,m1,m2,x1,x2;for(i=0;i<2*n-1;i++){hfmnode[i].weight=0;hfmnode[i].parent=-1;hfmnode[i].lchild=-1;hfmnode[i].rchild=-1;}for(i=0;i<n;i++){getchar();printf("请输入第%d片叶子的字符:",i+1);scanf("%c",&hfmnode[i].data);printf("请输入第%d片叶子的权重:",i+1);scanf("%d",&hfmnode[i].weight);}for(i=0;i<n-1;i++){m1=m2=MAXVALUE; //m1和m2分别用来存储叶子结点权值的最小值和次小值x1=x2=0; //x1和x2分别用来存储m1和m2的位置for(j=0;j<n+i;j++){if(hfmnode[j].weight<m1&&hfmnode[j].parent==-1){m2=m1;x2=x1;m1=hfmnode[j].weight;x1=j;}else if(hfmnode[j].weight<m2&&hfmnode[j].parent==-1){m2=hfmnode[j].weight;x2=j;}}hfmnode[x1].parent=n+i;hfmnode[x2].parent=n+i;hfmnode[n+i].weight=hfmnode[x1].weight+hfmnode[x2].weight;//父结点的权重是左孩子和右孩子的权重之和hfmnode[n+i].lchild=x1;hfmnode[n+i].rchild=x2;}}//显示叶子的编码字符和编码字符对应的二进制编码void showCode(HFMCode hfmcode[MAXNODE],HFMNodehfmnode[MAXNODE],int n){int i,j,k,c,p;HFMCode cd;for(i=0;i<n;i++){hfmcode[i].length=0; hfmcode[i].start=0;k=hfmcode[i].start;cd.start=n-1;c=i;p=hfmnode[c].parent;while(p!=-1){if(hfmnode[p].lchild==c) {cd.bit[cd.start]=0;}else{cd.bit[cd.start]=1;}cd.start--;c=p;p=hfmnode[c].parent;}for(j=cd.start+1;j<n;j++) {hfmcode[i].bit[k]=cd.bit[j];k++;hfmcode[i].length++; //length计算存放的二进制编码的位数}}for(i=0;i<n;i++) //输出每个叶子节点的哈夫曼编码{printf("第%d片叶子的编码是:",i+1);printf("%c\t",hfmnode[i].data);for(j=hfmcode[i].start;j<hfmcode[i].length;j++){printf("%d",hfmcode[i].bit[j]);}printf("\n");}}//输入字符串,得到二进制编码void compileCode(char str[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j,k;for(i=0;str[i]!='\0';i++){for(j=0;j<n;j++){if(str[i]==hfmnode[j].data){for(k=hfmcode[j].start;k<hfmcode[j].length;k++){printf("%d",hfmcode[j].bit[k]);}}}}printf("\n\n");}//输入二进制编码得到字符串void decompileCode(char num[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j;j=2*n-2; //哈夫曼树根结点的位置for(i=0;num[i]!='\0';i++){if(num[i]=='0'){j=hfmnode[j].lchild;}else if(num[i]=='1'){j=hfmnode[j].rchild;}if(j<n) //j大于等于n表示的都是除叶子结点以外的哈夫曼树结点{printf("%c",hfmnode[j].data);j=2*n-2;}}printf("\n");}//主函数void main(){HFMNode hfmnode[MAXNODE];HFMCode hfmcode[MAXLEAF];char str[100]; //存放输入的需要编译的的字符串char num[100]; //存放输入的需要编译的二进制字符串int n; //输入的叶子结点数//哈夫曼编码器printf("-----------------哈弗曼编码器------------------\n"); printf("请输入叶子结点数:");scanf("%d",&n);createHFMTree(hfmnode,n);showCode(hfmcode,hfmnode,n);//哈夫曼译码器printf("-----------------哈夫曼译码器------------------\n"); printf("请输入编码:\n");scanf("%s",str);compileCode(str,n,hfmcode,hfmnode);printf("请输入需要译码的数字:\n");scanf("%s",num);decompileCode(num,n,hfmcode,hfmnode); }。

哈夫曼编码译码器

哈夫曼编码译码器

i++;哈夫曼编码译码器#include<stdio.h> #include<conio.h>#include<malloc.h>#include<string.h> #include<stdlib.h> #define ERROR 0; #define OK 1;typedef int Status;typedef struct{ unsigned int weight; int key;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char * * HuffmanCode;int **KEY;int N;Status GetData(){ FILE *fp;int key[100][2]; int ch,k,i,tem; char str[16];fp=fopen("data.txt","r");k=0;while(!feof(fp)){ ch=fgetc(fp);i=0;while(ch!=' '){ str[i]=ch;ch=fgetc(fp);str[i]='\0';6H LU 2-(d 」)9%4HLP宀XO2S 丄0=>IM雯莎s-①宀」丄一S A雯 )((=悭炸=ss)dEO」lsw=s s )d E O 」l s-=l A P &=)££」g)(++壬VXO上)」0」山 U」m2)0aM)七二* 1UW0S一 s *>l )o o __e E (: luDHAmy◎=査雯」0=査雯-=三|3£。

&=)主」壬KEY[i][0]=key[i][0]; KEY[i][1]=key[i][1]; }N=k;fclose(fp);return OK;Status InitHuffmanTree(HuffmanTree &HT){ int i; HT=(HTNode *)malloc((2*N-1)*sizeof(HTNode)); if(!HT){ return ERROR;for(i=0;i<N;i++){HT[i].weight=KEY[i][1]; HT[i].key=KEY[i][0];HT[i].parent=-1;HT[i].lchild=-1;HT[i].rchild=-1;for(;i<2*N-1;i++){HT[i].parent=-1;return OK;void Select(HuffmanTree &HT,int n,int &fi,int&si){ int i=0,tem;if(n>=2){while(((HT+i)->parent)!=-1){ i++;fi=i;i++;while((HT+i)->parent!=-1){ i++;si=i;if((HT+fi)->weight>(HT+si)->weight){ tem=fi;fi=si;si=tem;for(i++;i<n;i++){ if((HT+i)->parent==-1){ if((HT+i)->weight<(HT+fi)->weight){ si=fi;fi=i;else{ if((HT+i)->weight<(HT+si)->weight){ si=i; int HuffmanTreeAllReady(HuffmanTree HT,int m){ int sum=0,i;for(i=0;i<m;i++){ if((HT+i)->parent==-1){ sum++; if(sum>1){ return 0;}return 1;void CreateHuffmanTree(HuffmanTree &HT,int n){ int s1,s2;while(!HuffmanTreeAllReady(HT,n)){ Select(HT,n, s1,s2);HT[n].parent=-1;HT[n].lchild=s1;HT[n].rchild=s2;HT[n].weight=HT[s1].weight+HT[s2].weight;HT[s1].parent=n;HT[s2].parent=n;n++;void HuffmanCoding(HuffmanTree&HT,HuffmanCode &HC,int n){ char * str; int len=0,tem,i,j;unsigned int p;str=(char *)malloc(n*sizeof(char));for(i=0;i<n;i++){ p=i;len=0;while((tem=HT[p].parent)!=-1){ if(HT[tem].lchild==p){ str[len]='0';else{ str[len]='1';len++;p=tem;HC[i]=(char *)malloc((len+1)*sizeof(char)); if(HC[i]){ for(j=0;j<len;j++){HC[i][j]=str[len-1-j];H c ==_e n 〒§S2_en一—prin 戈・%dw2rrHC==0二en)二void oufpufHuffmancode(HuffmancodeHe)宀Hrfo 「(no天N =++)宀Pl1mf(=%c .V&sw 「KEY==0LHC=2void coding(HuffmancodeHe)宀F 一LE*fpwinfchhfpHfopen(=旺口®金洱Ixw)二qHfopewchHfgefc(fp)-wh=e(ch 一heof)宀e-se 宀fpufs(HCSJq=fc-ose(fp)-fc-ose(fq)-prinm.oKW)voidDecoding(HuffmanT 「ee HTjnfN XF一LE*fpw infchhfqHfopen(=孺曲金洱.s 「=w+)fpHfopen(=chHfgefc(fp=wh=e(ch 一heof)宀亓2*N2wh=e(HTS._chi_d一卩」ggHTS.「chi_d卩」)宀if(chHHO)宀fHHTS._ch云e-se宀亓HTS.「chi_a—prin戈・%?ch)- chHfgefc(fp)-//printf("%c",ch); fputc(HT[t].key,fq); //printf("%c",HT[t].key); //printf("%s",HC[t]); //ch=fgetc(fp);fclose(fp);fclose(fq);printf("OK\n");int main(){HuffmanTree HT;HuffmanCode HC;int n,i,j,a,b,x;GetData();HC=(char * *)malloc((N)*sizeof(char *));InitHuffmanTree(HT);CreateHuffmanTree(HT,N);HuffmanCoding(HT,HC,N); //for(i=0;i<2*N-1;i++){ //printf("%d,%d,%d,%c,%d,%d\n",i,HT[i].parent,HT[i].weight, HT[i].key,HT[i].lchild,HT[i].rchild);//}printf(" 选项:1. 输出哈夫曼编码2. 输入明文得到密文3. 输入密文得到明文0.退出\n");printf(" 输入选项:");while(scanf("%d",&x),x){ switch(x){case 1 :{OutputHuffmanCode(HC); break;case 2 :{Coding(HC);case 3 :{Decoding(HT,N);printf(" 输入: 1. 输出哈夫曼编码2. 输入明文得到密文3. 输入密文得到明文0.退出\n");printf(" 输入选项:");return 0;}。

哈夫曼编码译码器代码及运行图示

哈夫曼编码译码器代码及运行图示
printf("按Enter继续:\t Input Enter to continue:\n");
ch=getchar();
while(ch!='q') /*当键入’q’时程序运行结束*/
{Explain();
while(ch!='r'&&ch!='c'&&ch!='e'&&ch!='d'&&ch!='q')
typedef char * *HuffmanCode;
/*函数声明*/
void readdata(elemtype *w);/*读取字符信息*/
huffmantree createhuff(elemtype *w);/*建立哈弗曼树*/
char * *huffmancode(huffmantree ht);/*哈弗曼编码*/
w[24].data='x' ;w[25].data='y' ;
w[26].data='z' ;
printf("If you input new char weight yourself y/n:\t是否自己输入字符频度y/n:\n");
zf=getchar();
while(zf!='n'&&zf!='y'&&zf!='q')
p->weight=w->weight;
}
else
{p->data='\0';
p->weight=0;

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言引言哈夫曼编码是一种用于无损数据压缩的编码方式,它利用出现频率较高的字符使用较短的编码,而出现频率较低的字符使用较长的编码。

通过这种方式可以使得编码后的数据占据较少的存储空间。

本文将介绍如何使用C语言实现一个哈夫曼编码译码器的数据结构。

哈夫曼树哈夫曼树是哈夫曼编码的关键数据结构,它可以通过给定的字符频率构建出一棵树。

在哈夫曼树中,每个字符都有一个对应的叶子节点,而非叶子节点表示编码的中间过程。

具体构建哈夫曼树的步骤如下:1. 统计每个字符的出现频率。

2. 将每个字符及其频率构建成一个节点,并按照频率从小到大排序。

3. 从频率最小的两个节点开始,合并成一个新节点,并将新节点的频率设为两个节点频率之和。

4. 将新节点插入到节点列表中,保持节点列表有序。

5. 重复步骤3和步骤4,直到只剩下一个节点,这个节点就是哈夫曼树的根节点。

编码在构建了哈夫曼树之后,我们可以根据树的结构来进行编码。

对于每个字符,其编码是由根节点到对应叶子节点路径上的边来表示的。

具体编码的步骤如下:1. 从根节点开始,递归遍历哈夫曼树的每个节点。

2. 如果当前节点为叶子节点,记录下从根节点到该叶子节点所经过的路径上的边的取值(0表示左边,1表示右边),得到该字符的编码。

3. 对于每个字符,将其编码存储起来以便后续使用。

译码译码的过程与编码相反,我们可以根据编码来找到对应的字符。

具体译码的步骤如下:1. 从哈夫曼树的根节点开始,逐个读取待译码的数据。

2. 如果读取的数据为0,移动到左子节点;如果读取的数据为1,移动到右子节点。

3. 如果移动到了叶子节点,记录下该叶子节点对应的字符,并回到根节点。

4. 重复步骤2和步骤3,直到读取完毕所有的数据,得到原始的字符序列。

实现下面是一个用C语言实现的哈夫曼编码译码器的数据结构示例:```cinclude <stdio.h>typedef struct Node {char character;int frequency;struct Node left;struct Node right;} Node;typedef struct HuffmanTree {Node root;} HuffmanTree;HuffmanTree buildHuffmanTree(char characters, int frequencies, int size) {// 构建哈夫曼树的代码实现}void encode(HuffmanTree tree, char string, char encodedString) {// 编码的代码实现}void decode(HuffmanTree tree, char encodedString, char decodedString) {// 译码的代码实现}int mn() {// 测试代码}```总结通过本文,我们了解了哈夫曼编码译码器的数据结构及其在C 语言中的实现。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构c语言哈夫曼编码译码器数据结构目录1.引言1.背景2.目的3.范围2.哈夫曼编码概述1.哈夫曼树2.哈夫曼编码3.哈夫曼译码3.数据结构设计1.哈夫曼树结构2.编码表结构3.输入数据结构4.输出数据结构4.算法实现1.哈夫曼树构建算法2.编码表算法3.哈夫曼编码算法4.哈夫曼译码算法5.使用示例1.编码示例2.译码示例6.性能分析1.时间复杂度分析2.空间复杂度分析7.风险和限制1.输入数据限制2.输出数据限制3.算法限制8.附录1.示例代码2.测试数据3.参考文献1.引言1.1 背景哈夫曼编码是一种经典的数据压缩算法,通过构建哈夫曼树,将输入的数据进行编码。

哈夫曼编码的特点是可变长度编码,频率高的字符使用短编码,频率低的字符使用长编码。

1.2 目的本文档旨在详细介绍哈夫曼编码译码器的数据结构设计和算法实现,帮助读者理解和使用该编码器。

1.3 范围本文档涵盖了哈夫曼编码和译码的概述,数据结构设计,算法实现,使用示例以及性能分析。

2.哈夫曼编码概述2.1 哈夫曼树哈夫曼树是一种特殊的二叉树,用于构建哈夫曼编码。

它通过合并两个最小频率的节点来构建树,直到所有节点都被合并。

2.2 哈夫曼编码哈夫曼编码是将字符映射为可变长度的二进制码。

频率高的字符使用短码,频率低的字符使用长码。

编码表中保存了每个字符对应的编码。

2.3 哈夫曼译码哈夫曼译码是根据哈夫曼编码,将二进制码转换为原始字符。

3.数据结构设计3.1 哈夫曼树结构哈夫曼树的结构包含一个根节点和左右子节点。

```ctypedef struct huffmanTreeNode {char data; // 节点字符数据int frequency; // 节点字符出现的频率struct huffmanTreeNode left; // 左子节点指针struct huffmanTreeNode right; // 右子节点指针} huffmanTreeNode;```3.2 编码表结构编码表结构用于保存字符和对应编码的映射关系。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《数据结构》课程设计目录1. 问题描述……………………………………………第 2页2. 系统设计……………………………………………第 2页3. 数据结构与算法描述………………………………第 5页4. 测试结果与分析……………………………………第 6页5. 总结 (10)6. 参考文献 (10)附录程序源代码 (11)课程设计题目1. 问题描述利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。

试为这样的信息传输写一个哈夫曼编/译码系统。

2. 系统设计2.1 设计目标一个完整的系统应具有以下功能:1)I:初始化(Initialization)。

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

输出哈夫曼树,及各字符对应的编码。

2)W:输入(Input)。

从终端读入需要编码的字符串s,将字符串s存入文件Tobetran.txt中。

3)E:编码(Encoding)与译码(Decoding)。

编码(Encoding)。

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

译码(Decoding)。

利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

印代码文件(Print)。

将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码写入文件CodePrint中。

4)T:印哈夫曼树(Tree Printing)。

将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

5)Q:退出程序。

返回WINDOWS界面。

2.2 设计思想哈夫曼编码(Huffman Coding)是一种编码方式,以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。

是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。

这种方法是由David.A.Huffman发展起来的。

例如,在英文中,e的出现概率很高,而z的出现概率则最低。

当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。

用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。

二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。

倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

2.3 系统模块划分图2-3 哈夫曼编/解码器的程序结构图2.3.1 初始化算法:程序从文件abc.txt中获取26个英文字母的权值。

2.3.2 编码算法:(1)对输入的一段欲编码的字符串进行统计各个字符出现的次数,并它们转化为权值{w1,w2,……,wN}构成n棵二叉树的集合F={T1,T2,……,Tn}把它们保存到结构体数组HT[n]中,其中{Ti是按它们的ASCⅡ码值先后排序。

其中每棵二叉树Ti中只有一个带权为Wi的根结点的权值为其左、右子树上根结点的权值之和。

(2)在HT[1..i]中选取两棵根结点的权值最小且没有被选过的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左、右子树上根结点的权值之和。

(3)哈夫曼树已经建立后,从叶子到根逆向求每一个字符的哈夫曼编码。

2.3.3 译码算法:译码的过程是分解电文中字符串,从根出发,按字符'0',或'1'确定找左孩子或右孩子,直至叶子结点,便求的该子串相应字符并输出接着下一个字符。

3. 数据结构与算法描述3-1typedef struct{ int weight;int parent,lchild,rchild;}HTNode,* HuffmanTree; //动态分配数组存储赫夫曼树typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表3-2 int min(HuffmanTree t,int i) // ---------求赫夫曼编码-------------3-3 void select(HuffmanTree t,int i,int &s1,int &s2) //----slect函数----3-4void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)// w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC3-5 void Initialization() //----------初始化赫夫曼链表--------------3-6 void InputCode() //---------获取报文并写入文件-------------3-7 void Encoding() //----------------编码函数------------------3-8 void Decoding() //-----------------译码函数-----------------3-9 void Code_printing() //-------------打印编码的函数--------------3-19 void coprint(HuffmanTree start,HuffmanTree HT)//------------------------打印赫夫曼树的函数-----------------------3-20 void main() //--------------------主函数-------------------4. 测试结果与分析A 186B 64C 13D 22E 32F 103G 21 H 15 I 47 J 57 K 15 L 32M 20 N 57 O 63 P 15 Q 1 R 48S 51 T 80 U 23 V 8 W 18 X 1Y 16 Z 1表4-1 abc.txt文件中的字母和权值声明:程序预先将Huffman编码解码所需的26个字母和权值保存在根目录下的abc.txt文件下。

4-1.按照程序提示输入i对Huffman进行初始化。

4-2.初始化后程序对abc.txt文件中的数据进行读取并运行编码函数进行哈夫曼编码。

然后将字母、权值和哈夫曼编码存在根目录下的htmTree.txt文件中。

在屏幕显示出字符、权值、编码。

4-3.输入w进入待编码字符输入窗口,并键入字符串(注意单词间无空格)“happynewyear”。

4-4.可以看出所获得的字符串已经存入根目录下的tobetran.txt文件中。

4-5.输入e进行编码、译码和打印编码功能。

4-6.输入t打印哈夫曼树。

由于哈夫曼树过于巨大,一次截屏无法完全显示,使用两次截屏。

以上两幅图显示出来程序编出的哈夫曼树的形状。

打印出来的图形与教科书上的常见哈夫曼树略有不同,左边的数是右边数的父节点。

4-7.输入q退出程序。

5. 总结5-1、用户界面设计为“菜单”模式,使人们更加容易使用。

5-2、在程序的一次执行过程中,第一次执行e命令之后,哈夫曼树已经在内存了,不必再读入。

5-3.在编程中使用了很不规范的编程方法,应用了一些临时变量来实现功能,,而大量临时变量在代码中没有很好地进行命名。

这给程序的阅读和维护带来了极大的困难。

5-4.本程序仅能对26个小写字母构成的字符串进行处理,并不具有对汉字等的编码处理能力。

5-5.设计中得到了老师和广大同学的帮助,并参考了网络上的优秀论文和纸质文件,使我的程序设计能够较为顺利的进行下去。

在此我衷心感谢我的老师同学和对以上资源的作者。

6. 参考文献A:书籍资料[1] 李春葆《数据结构教程上机实验指导》北京:清华大学出版社[2] 严蔚敏吴伟民《数据结构(C语言版)》北京:清华大学出版社[3] 苏仕华《数据结构课程设计》北京:机械工业出版社B:网络资料[1] 哈夫曼编/译码器(课程设计)/living/blog/item/d302367a65804eed2e73b32b.html[2]哈夫曼编码/hihinet/blog/item/432169091693efce3bc763ab.html附录程序源代码//哈夫曼编/译码器(课程设计) 2008/5/21#include <iostream.h>#include <fstream.h>#include <iomanip.h>#include <string.h>#include <malloc.h>#include <stdio.h>#include <iomanip.h>const int UINT_MAX=10000;typedef struct{int weight;int parent,lchild,rchild;}HTNode,* HuffmanTree; //动态分配数组存储赫夫曼树typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表//--------------------全局变量-----------------------HuffmanTree HT;HuffmanCode HC;int *w,i,j;const int n=26;char *z;int flag=0;int numb=0;// -----------------求赫夫曼编码---------------------int min(HuffmanTree t,int i){ // 此函数将要被void select()调用int j,flag;int k=UINT_MAX; // 取k为不小于可能的值for(j=1;j<=i;j++)if(t[j].weight<k&&t[j].parent==0)k=t[j].weight,flag=j;t[flag].parent=1;return flag;}//--------------------slect函数----------------------void select(HuffmanTree t,int i,int &s1,int &s2){ // s1为最小的两个值中序号小的那个int j;s1=min(t,i);s2=min(t,i);if(s1>s2){j=s1;s1=s2;s2=j;}}// -------------------参考课本算法6.12-------------------void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){ // w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC int m,i,s1,s2,start;int c,f;HuffmanTree p;char *cd;if(n<=1)return;//检测结点数是否可以构成树m=2*n-1;HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用for(p=HT+1,i=1;i<=n;++i,++p,++w){p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;}for(;i<=m;++i,++p)p->parent=0;for(i=n+1;i<=m;++i) // 建赫夫曼树{ //在HT[1~i-1]中选择parent=0且weight最小的两个结点,其序号分别为s1和s2 select(HT,i-1,s1,s2);HT[s1].parent=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个字符编码的头指针向量([0]不用)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';elsecd[--start]='1';HC[i]=(char*)malloc((n-start)*sizeof(char));// 为第i个字符编码分配空间strcpy(HC[i],&cd[start]); // 从cd复制编码(串)到HC}free(cd); // 释放工作空间}//----------------------初始化赫夫曼链表-------------------------void Initialization(){flag=1;int num2;cout<<"下面初始化赫夫曼链表"<<endl;w=(int*)malloc(n*sizeof(int)); // 为第26个字符权值分配空间z=(char*)malloc(n*sizeof(char)); // 为第26个字符分配空间cout<<"\n依次显示"<<n<<"个字符与其权值和编码\n"<<endl;char base[2];//?ifstream fin("abc.txt");for(i=0;i<n;i++){fin>>base;*(z+i)=*base;//?fin>>num2;//上面123行*(w+i)=num2;}HuffmanCoding(HT,HC,w,n);//----------------------------------打印编码---------------------------------------cout<<"字符"<<setw(6)<<"权值"<<setw(11)<<"编码"<<endl;for(i=1;i<=n;i++){cout<<setw(3)<<*(z+i-1);cout<<setw(6)<<*(w+i-1)<<setw(12)<<HC[i]<<endl;}//--------------------------将赫夫曼编码写入文件----------------------------cout<<"下面将赫夫曼编码写入文件"<<endl<<"...................."<<endl;FILE *htmTree;char r[]={' ','\0'};if((htmTree=fopen("htmTree.txt","w"))==NULL){cout<<"不能打开文件"<<endl;return;}for(i=0;i<n;i++){fputc(*(z+i),htmTree);fputs(r,htmTree);}for(i=0;i<n;i++){fprintf(htmTree,"%6d",*(w+i));fputs(r,htmTree);}for(i=1;i<=n;i++){fputs(HC[i],htmTree);fputs(r,htmTree);}fclose(htmTree);cout<<"已将字符与对应编码写入根目录下文件htmTree.txt中"<<endl<<endl; }//--------------------------获取报文并写入文件---------------------------void InputCode(){FILE *tobetran;char str[100];if((tobetran=fopen("tobetran.txt","w"))==NULL){cout<<"不能打开文件"<<endl;return;}cout<<"请输入你想要编码的字符"<<endl; //字符个数应当小于100 gets(str);fputs(str,tobetran);cout<<"获取报文成功"<<endl;fclose(tobetran);cout<<"...................."<<endl<"报文存入根目录下的tobetran.txt文件中"<<endl; }//---------------------------------编码函数---------------------------------void Encoding(){cout<<"下面对目录下文件tobetran.txt中的字符进行编码"<<endl;FILE *tobetran,*codefile;if((tobetran=fopen("tobetran.txt","rb"))==NULL){cout<<"不能打开文件"<<endl;}if((codefile=fopen("codefile.txt","wb"))==NULL){cout<<"不能打开文件"<<endl;}char *tran;i=99;tran=(char*)malloc(100*sizeof(char));while(i==99){if(fgets(tran,100,tobetran)==NULL){cout<<"不能打开文件"<<endl;break;}for(i=0;*(tran+i)!='\0';i++){for(j=0;j<=n;j++){if(*(z+j-1)==*(tran+i)){fputs(HC[j],codefile);if(j>n){cout<<"字符错误,无法编码!"<<endl;break;}}}}}cout<<"…………编码完成…………"<<endl;cout<<"编码写入目录下的codefile.txt中"<<endl<<endl;fclose(tobetran);fclose(codefile);free(tran);}//-------------------------译码函数---------------------------void Decoding(){cout<<"下面对根目录下文件codefile.txt中的字符进行译码"<<endl;FILE *codef,*txtfile;if((txtfile=fopen("\\Textfile.txt","w"))==NULL){cout<<"不能打开文件"<<endl;}txtfile=fopen("Textfile.txt","w");if ((codef=fopen("codefile.txt","r"))==NULL){cout<<"不能打开文件"<<endl;}codef=fopen("codefile.txt","r");char *work,*work2,i2;int i4=0,i,i3;unsigned long length=10000;work=(char*)malloc(length*sizeof(char));fgets(work,length,codef);work2=(char*)malloc(length*sizeof(char));i3=2*n-1;for(i=0;*(work+i-1)!='\0';i++){i2=*(work+i);if(HT[i3].lchild==0){*(work2+i4)=*(z+i3-1);i4++;i3=2*n-1;i--;}else if(i2=='0') i3=HT[i3].lchild;else if(i2=='1') i3=HT[i3].rchild;}*(work2+i4)='\0';fputs(work2,txtfile);cout<<"…………译码完成…………"<<endl;cout<<"内容写入根目录下的文件textfile.txt中"<<endl<<endl;free(work); //释放工作区free(work2); //释放工作区fclose(txtfile); //关闭文件txtfile.txtfclose(codef); //关闭文件codef.txt}//-----------------------打印编码的函数----------------------void Code_printing(){cout<<"下面打印根目录下文件CodePrin.txt中编码字符"<<endl;FILE * CodePrin,* codefile;if((CodePrin=fopen("CodePrin.txt","w"))==NULL){cout<<"不能打开文件"<<endl;return;}if((codefile=fopen("codefile.txt","r"))==NULL){cout<<"不能打开文件"<<endl;return;}char *work3;work3=(char*)malloc(51*sizeof(char));if(fgets(work3,51,codefile)==NULL){cout<<"不能读取文件"<<endl;}elsedo{fputs(work3,CodePrin);puts(work3);}while(strlen(work3)==50&&fgets(work3,51,codefile)!=NULL);free(work3);cout<<"打印结束"<<endl<<endl;fclose(CodePrin);fclose(codefile);}//------------------------打印赫夫曼树的函数-----------------------void coprint(HuffmanTree start,HuffmanTree HT) //start=ht+26这是一个递归算法{if(start!=HT){FILE * TreePrint;if((TreePrint=fopen("TreePrint.txt","a"))==NULL){cout<<"创建文件失败"<<endl;return;}numb++; //number=0 该变量为已被声明为全局变量coprint(HT+start->rchild,HT); //递归先序遍历cout<<setw(5*numb)<<start->weight<<endl;fprintf(TreePrint,"%d\n",start->weight);coprint(HT+start->lchild,HT);numb--;fclose(TreePrint);}}void Tree_printing(HuffmanTree HT,int w){HuffmanTree p;p=HT+w; //p=HT+26cout<<"下面打印赫夫曼树"<<endl;coprint(p,HT); //p=HT+26cout<<"打印工作结束"<<endl;}//----------------------------------主函数-------------------------------------void main(){cout<<endl;cout<<" 此程序经晓光修改"<<endl;cout<<" 实现赫夫曼编码解码功能"<<endl;char choice;while(choice!='q'){ cout<<"\n******************************"<<endl;cout<<" 赫夫曼编码解码"<<endl;cout<<"****************************** "<<endl;cout<<"(i)初始化赫夫曼表"<<endl;cout<<"(w)输入待编码的字符"<<endl;cout<<"(e)进行编码、译码、打印编码"<<endl;cout<<"(t)打印赫夫曼树"<<endl;cout<<"(q)离开"<<endl;if(flag==0){cout<<"\n请先初始化赫夫曼链表,输入'i'"<<endl;cout<<"(程序将从根目录下的abc.txt文件中读出26个字母及其权值并对字母进行编码)"<<endl;}cin>>choice;switch(choice){case 'i':Initialization();//初始化赫夫曼表break;case 'w':InputCode(); //输入待编码的字符break;case 'e':Encoding();//进行编码Decoding();//进行译码Code_printing();//打印编码break;case 't':Tree_printing(HT,2*n-1);//打印26个字母权值形成的哈夫曼树break;case 'q': //退出程序break;default:cout<<"输入命令错误"<<endl;}}free(z);//释放字母所占内存空间free(w);//释放权值所占内存空间free(HT); //释放HT结构体所占内存空间}//代码结束code over。

相关文档
最新文档