数据结构 哈夫曼编码
Posted Ice丨shine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构 哈夫曼编码相关的知识,希望对你有一定的参考价值。
目录
一、需求分析
功能需求:
设计并实现一个写一个哈夫曼码的编/译码系统,系统功能包括:
(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 中。
界面需求:
可以输入哈夫曼编码所需的字符及权值,打印出哈夫曼树结构和各个字符的哈夫曼编码。读取字符串可以进行编码和解码并输出,输出在TXT文件中展示
二、概要设计
模块层次结构设计
Initialhuffman()进行初始化
Encoding()进行编码
Decoding()进行解码
Codeprint()将CodeFile.txt的数据紧凑打印在终端上
接口设计
int MinVal(HuffmanTree tree,int i);//在前i个节点中选择parent为-1且weight最小的结点,返回其序号
void Select(HuffmanTree tree,int i,int *s1,int *s2);//设定s1序号更小
void Display(HuffmanTree tree);//打印哈夫曼树并将其输出至TreePrint.txt(直观)和hfmTree.txt(供读取)文件
int huffcode(HuffmanTree tree, huffmanCodex code);//编码并写入文件中
int incode(HuffmanTree tree, huffmanCodex code); //对每一个字符进行编码
int decode(HuffmanTree tree);//用树对CodeFile.txt进行解码并输出至TextFile.txt中
void CodePrint();//将CodeFile.txt中的数据改为50个一行并存入CodePrin.txt中
数据结构设计
struct HTNode
char ch;
int weight,lchild,rchild,parent;
;//哈夫曼树结点结构
typedef struct
struct HTNode ht[1024];
int htsize;
Huffman,*HuffmanTree;//哈夫曼树结构
typedef struct
char bits[50];
char ch;
huffmanCode,*huffmanCodex;//哈夫曼编码结构
三、详细设计
Initialhuffman.cpp内容如下:
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
struct HTNode
char ch;
int weight,lchild,rchild,parent;
;//哈夫曼树结点结构
typedef struct
struct HTNode ht[1024];
int htsize;
Huffman,*HuffmanTree;//哈夫曼树结构
//在前i个节点中选择parent为-1且weight最小的结点,返回其序号
int MinVal(HuffmanTree tree,int i)
int j,k,min=-1;
for(j=0;j<i;j++)
if(tree->ht[j].parent==-1&&min==-1)
min=tree->ht[j].weight; //将第一个双亲为空的点置为最小值
k=j;
break;
for(j=0;j<i;j++)
if(tree->ht[j].parent==-1&&tree->ht[j].weight<min)
min=tree->ht[j].weight;
k=j;
tree->ht[k].parent=-2;//置双亲非空
return k;
void Select(HuffmanTree tree,int i,int *s1,int *s2)//设定s1序号更小
int s;
*s1 = MinVal(tree,i);
*s2 = MinVal(tree,i);
if(*s1>*s2)
s=*s1;
*s1=*s2;
*s2=s;
void Display(HuffmanTree tree)
int i;
//定义文件指针
FILE *f = NULL,*fp = NULL;
//打开文件
f = fopen("TreePrint.txt","w");
fp =fopen("hfmTree.txt","w");
if(f==NULL||fp==NULL)
printf("文件读取失败!\\n");
char buf[1024];
//写文件
strcpy(buf,"下标 字符 权值 左孩子 右孩子 双亲\\n");
fputs(buf,f);
fprintf(fp,"%d\\n",tree->htsize);
printf("下标 字符 权值 左孩子 右孩子 双亲\\n") ;
for(i=1;i<=tree->htsize;i++)//将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中
fprintf(f,"%d",i);
fprintf(f,"%12c",tree->ht[i].ch);
fprintf(f,"%12d",tree->ht[i].weight);
fprintf(f,"%12d",tree->ht[i].lchild);
fprintf(f,"%12d",tree->ht[i].rchild);
fprintf(f,"%12d\\n",tree->ht[i].parent);
fprintf(fp,"%d ",i);
fprintf(fp,"%c " ,tree->ht[i].ch);
fprintf(fp,"%d ",tree->ht[i].weight);
fprintf(fp,"%d ",tree->ht[i].lchild);
fprintf(fp,"%d ",tree->ht[i].rchild);
fprintf(fp,"%d\\n",tree->ht[i].parent);
fprintf(f,"_______________________________________________\\n");
printf("%d",i);
printf("%9c",tree->ht[i].ch);
printf("%9d",tree->ht[i].weight);
printf("%9d",tree->ht[i].lchild);
printf("%9d",tree->ht[i].rchild);
printf("%9d\\n",tree->ht[i].parent);
printf("_______________________________________________\\n");
fclose(f);//关闭文件
int main()//初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中
int n,i;
printf("请输入字符集大小:");
scanf("%d",&n);
getchar();
int total = 2 * n -1;
HuffmanTree tree = (HuffmanTree)malloc(total * sizeof(Huffman));
tree->htsize = total;
for(i=1;i<=n;i++)//下标从1开始
printf("请输入字符%d:",i);
scanf("%c",&tree->ht[i].ch);
getchar();
printf("请输入该字符的权重:");
scanf("%d",&tree->ht[i].weight);
getchar();
tree->ht[i].lchild=-1;
tree->ht[i].rchild=-1;
tree->ht[i].parent=-1;
int s1,s2;
for(;i<=tree->htsize;++i)
Select(tree,i,&s1,&s2);
//将两个最小结点合并成新节点,并接在静态链表后
tree->ht[s1].parent=tree->ht[s2].parent=i;
tree->ht[i].lchild=s1;
tree->ht[i].rchild=s2;
tree->ht[i].parent=-1;
tree->ht[i].weight=tree->ht[s1].weight+tree->ht[s2].weight;
tree->ht[i].ch=NULL; //非树叶结点无字符
Display(tree);
return 0;
Encoding.cpp内容如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 16
struct HTNode
char ch;
int weight,lchild,rchild,parent;
;//哈夫曼树结点结构
typedef struct
struct HTNode *ht;
int htsize;
Huffman,*HuffmanTree;//哈夫曼树结构
typedef struct
char bits[50];
char ch;
huffmanCode,*huffmanCodex;//哈夫曼编码结构
void Display(HuffmanTree tree)
int i;
printf("下标 字符 权值 左孩子 右孩子 双亲\\n") ;
for(i=1;i<=tree->htsize;i++)
printf("%d",i);
printf("%9c",tree->ht[i].ch);
printf("%9d",tree->ht[i].weight);
printf("%9d",tree->ht[i].lchild);
printf("%9d",tree->ht[i].rchild);
printf("%9d\\n",tree->ht[i].parent);
printf("_______________________________________________\\n");
//对每一个字符进行编码
int incode(HuffmanTree tree, huffmanCodex code)
int i, parent, child;
huffmanCode temp;
char cd[tree->htsize];
int start;//记录尾结点
for (i = 1; i <= (tree->htsize+1)/2; i++)
child = i;
temp.ch=tree->ht[i].ch;
parent = tree->ht[child].parent;
start = tree->htsize;
while (parent != -1) //从叶子到根逆向求编码
if (tree->ht[parent].lchild == child)
cd[--start] = '0';
else
cd[--start] = '1';
child = parent;
parent = tree->ht[child].parent;
int j;
//将序列倒序储存
for(j=start;j<tree->htsize;j++)
temp.bits[j-start]=cd[j];
temp.bits[j-start]='\\0'; //在末尾加上标识符
code[i] = temp;
//编码并写入文件中
int huffcode(HuffmanTree tree, huffmanCodex code)
char c;
int j, index;
FILE *write;
char buf[1024]; //缓冲区
FILE *fp; //文件指针
int len; //行字符个数
if((fp = fopen("ToBeTran.txt","r")) == NULL)
printf("fail to read");
return 0;
while(fgets(buf,1024,fp) != NULL)
len = strlen(buf);
buf[len] = '\\0'; //去掉换行符
printf("%s %d \\n",buf,len);
fclose(fp);
if ((write = fopen("CodeFile.txt", "w")) == NULL)
printf("文件读取失败\\n");
return 0;
int i;
for(j=0;j<len;j++)
//printf("测试点2\\n");
for(i=1;i<(tree->htsize+1)/2;i++)
if(buf[j]==code[i].ch) //逐个比较并输出编码
fputs(code[i].bits,write);
break;
fclose(fp);
fclose(write);
return 0;
int main()//利用以建好的哈夫曼树,对文件ToBeTran 中的正文进行编码,然后将结果存入文件CodeFile中
char buf[1024]; //缓冲区
FILE *fp; //文件指针
int len; //行字符个数
if((fp = fopen("ToBeTran.txt","r")) == NULL)
printf("fail to read");
return 0;
while(fgets(buf,1024,fp) != NULL)
len = strlen(buf);
buf[len] = '\\0'; //去掉换行符
printf("ToBeTran中的内容为:%s 长度:%d \\n",buf,len );
fclose(fp);
FILE *f=NULL;
f=fopen("hfmTree.txt","r");
if(!f)
printf("error!\\n");
return 0;
int n;
fscanf(f,"%d\\n",&n);
HuffmanTree tree = (HuffmanTree)malloc(n * sizeof(Huffman));
tree->htsize=n;
int i,j;
//读取哈夫曼树
for(i=1;i<=tree->htsize;i++)
fscanf(f,"%d ",&j);
fscanf(f,"%c %d %d %d %d\\n",&tree->ht[i].ch,&tree->ht[i].weight,&tree->ht[i].lchild,&tree->ht[i].rchild,&tree->ht[i].parent哈夫曼编码译码