只是记录一下自己写作业的过程,我不是一个程序员,我是一个想进德云社的闲散人员
一.自己对huffman树的理解
先用程序读入一篇或多篇英文文章,把文章中出现的每一个字符都当做树结构中的一个节点,并且给每个节点附上一个权值(该字符在文章中出现的次数),通过这些权值,构成最小生成树。这就是huffman树的建立过程。最小生成树建立好以后,每个字符都会有一个由二进制数构成的编码,可以根据这些编码对一串二进制树解码,把二进制数还原成字符。具体内容会在程序中讲解。
二.程序讲解
# include <stdio.h>
# include <stdlib.h>
# include "huffman.h"
int main()
{
char *rf = read_file("1.txt");//读入文档内容
htTree * codeTree = buildTree(rf);//建立huffman树
hlTable *codeTable = buildTable(codeTree);//建立编码表
char *enco = read_file("encode.txt");
char* deco = encode(codeTable,enco);//对读入字符串编码
decode(codeTree,deco);对读入字符串解码
return 0;
}
1.read_file函数讲解
上面已经提到过huffman就是通过读入一写字符,根据每个字符的出现次数生成最小生成树,那么如何读入字符内容呢。我选择从txt文档里读入。先看一下这个函数的代码吧
char* read_file(char *fname)
{
FILE*fp = fopen(fname,"rb");
char arr[100][256];
char *str;
int len=0;
int i=0;
while(fgets(arr[i],256,fp)!=NULL)
{
i++;
}
fclose(fp);
str = (char*)malloc(sizeof(char)*256*(i));
memset(str,0,sizeof(char)*256*(i));
for(int j=1;j<=i;j++)
{
strcat(str,arr[j-1]);
}
return str;
}
这里需要思考的一个问题是如何读入多行文档。用fgets函数可以很好解决。根据我个人了解,fgets函数每次都能读入一行文档,如果文档有多行,再次使用fgets函数读取文档时,就会读取下一行。直到 fgets(arr[i],256,fp)!=NULL的时候,说明多行文档已经读入完毕。每次读取一行内容的时候都会存到二维数组arr中。fgets函数会自动在第一个参数数组的末尾加上结束符’\0’.
于此同时通过i++,来得到当行文档总共有多少行。一次来获得要存入全部文档总共需要的一个大概内存。(char*)malloc(sizeof(char)256(i)),假设每行有256个字符,在这里肯定会浪费一些空间,这里就留给你们去修改。然后通过memset初始化字符串空间。
然后吧文档的每行内容存到str指向的空间。这样就完成了对当行字符的读入并用一个指针指向这些字符内容,并返回。
2.buildTree函数内容讲解
htTree * buildTree(char *inputString)//建立Huffman树
{
int *probablity = (int*)malloc(sizeof(int)*256);//整数数组
for(int i=0;i<256;i++)
{
probablity[i]=0;//整数数组初始化
}
for(int j=0;inputString[j]!='\0';j++)
{
probablity[(unsigned int)inputString[j]]++;//当读入的字符串不结束时,一直循环,对应ascall编码的整数下标的数组元素+1
}//出现次数用作权值
pQueue * huffmanqueue = NULL;
huffmanqueue = iniPQueue(huffmanqueue);//生成并初始化huffamn树队列
for(int k=0;k<256;k++)
{