数据结构第五次作业——Huffman 编码
18级第五次作业(树)—Huffman编码文件压缩
我这里没有用到位运算,输入进output文件里面的仅仅是字符’0’和‘1’
【问题描述】
编写一程序采用Huffman编码对一个正文文件进行压缩。具体压缩方法如下:
- 对正文文件中字符(换行字符’'除外,不统计)按出现次数(即频率)进行统计
- 依据字符频率生成相应的Huffman树(未出现的字符不生成)
- 依据Huffman树生成相应字符的Huffman编码
- 依据字符Huffman编码压缩文件(即按照Huffman编码依次输出源文件字符)。
说明:
只对文件中出现的字符生成Huffman,注意:一定不要处理\n,即不要为其生成Huffman码。
采用ASCII码值为0的字符作为压缩文件的结束符(即可将其出现次数设为1来参与编码).
在生成Huffman树时,初始在对字符频率权重进行(由小至大)排序时,频率相同的字符ASCII编码值小的在前,在依次取出有序权重序列中权重最小的两个节点时将分别作为新生成树的左右子节点;新生成的权重节点插入到有序权重序列中时,出现相同权重时,插入到其后(采用稳定排序)。
遍历Huffman树生成字符Huffman码时,左边为0右边为1。
源文件是文本文件,字符采用ASCII编码,每个字符占8位;而采用Huffman编码后,高频字符编码长度较短(小于8位),因此最后输出时需要使用C语言中的位运算将字符Huffman码依次输出到每个字节中。
【输入形式】
对当前目录下文件input.txt进行压缩。【输出形式】
将压缩后结果输出到文件output.txt中,同时将压缩结果用十六进制形式(printf("%x",…))输出到屏幕上,以便检查和查看结果。
【样例输入1】
若当前目录下input.txt中内容如下:
aaabbc
【样例输出1】
15f0
同时程序将压缩结果输出到文件output.txt中。
【样例说明】
输入文件中字符的频率为:a为3,b为2,c为1,此外,\0字符将作为压缩文件的结束标志,其出现次数设为1。因此,采用Huffman码生成方法,它们的Huffman编码分别为:
a : 0
b : 10
c : 111
\0 : 110
因此,最终文件压缩结果(按位)为:
0001010111110000
将上述结果按字节按十六进制输出到屏幕上则为15f0(即0001010 111110000的十六进制表示)。
说明:采用Huffman码输出字符序列长度为:1+1+1+2+2+3+3=13(位),由于C语言中输出的最小单位为字节(8位),因此,最后补了三个位0,压缩后实际输出为2个字节。由于文本文件是按ASCII来解释的,因此,以文本方式打开压缩文件将显示乱码(最好用二进制文件查看器来看)。
【样例输入2】
若当前目录下input.txt中内容如下:
do not spend all that you have.do not sleep as long as you want.
【样例输出2】
ea3169146ce9eee6cff4b2a93fe1a5d462d21d9a87c0eb2f3eb2a9cfe6cae
同时程序将压缩结果输出到文件output.txt中。
【评分标准】
通过所有测试点将得满分。
提交源文件:
注意: 只能用 C 语言编写程序。 如果有多个源文件,压缩成 rar 或者 zip 包提交。
解答:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define max 1000
#define sup_max 100000000
char sup[sup_max];
struct NODE
{
char ch;
int weight;
char a[max];
struct NODE *next,*lchild,*rchild;
};
struct CHA
{
char ch;
int weight;
} s[max];
typedef struct NODE* Node;
typedef struct NODE node;
Node head=NULL,tail,root;
Node insert(Node p)
{
if(head==NULL)
{
head=p;
}
else if(p->weight < head->weight || (p->weight == head->weight && p->ch < head->ch))
{
p->next=head;
head=p;
}
else
{
Node q,r;
q=head;
r=q->next;
while(1)
{
if(r==NULL)
{
q->next=p;
break;
}
else if(p->weight < r->weight || (p->weight == r->weight && p->ch < r->ch))
{
q->next=p;
p->next=r;
break;
}
else
{
q=q->next;
r=q->next;
}
}
}
return head;
}
Node insert_2(Node p)
{
Node q,r;
q=root;
r=q->next;
while(1)
{
if(r==NULL)
{
q->next=p;
break;
}
else if(p->weight >= q->weight && p->weight <r->weight)
{
q->next=p;
p->next=r;
break;
}
else
{
q=q->next;
r=q->next;
}
}
return root->next->next;
}
int k=0;
char code[max];
void inorder(Node t)
{
if(t->lchild==NULL && t->rchild==NULL)
{
strcpy(t->a,code);
return;
}
else
{
code[k++]='0';
inorder(t->lchild);
code[k]='\0';
k--;
code[k++]='1';
inorder(t->rchild);
code[k]='\0';
k--;
}
}
void preorder(Node t)
{
if(t->lchild==NULL && t->rchild==NULL)
{
//strcat(sup,t->a);
return ;
}
else
{
preorder(t->lchild);
preorder(t->rchild);
}
}
char pw[300][100];
void transform(Node t)
{
if(t->lchild==NULL && t->rchild==NULL)
{
strcpy(pw[t->ch],t->a);
return ;
}
else
{
transform(t->lchild);
transform(t->rchild);
}
}
int main()
{
Node p,q;
int i,j,k,len=0,t;
char ch;
FILE *in,*out;
if((in=fopen("D:\\test.txt","r"))==NULL)
{
printf("Can not open");
return 0;
}
if((out=fopen("D:\\out.txt","w"))==NULL)
{
printf("can not");
return 0;
}
while(1)
{
ch=fgetc(in);
if(ch=='\n')
continue;
if(ch==EOF)
{
ch=0;
}
for(i=0; i<len; i++)
{
if(ch==s[i].ch)
{
(s[i].weight)++;
break;
}
}
if(i==len)
{
s[len].ch=ch;
s[len].weight=1;
len++;
}
if(ch==0)
break;
}
for(i=0; i<len; i++)
{
//printf("%c %d\n",s[i].ch,s[i].weight);
p=(Node)malloc(sizeof(node));
p->ch=s[i].ch;
p->weight=s[i].weight;
p->next=p->lchild=p->rchild=NULL;
root=insert(p);
}
/* q=root;
while(q!=NULL)
{
printf("%c %d\n",q->ch,q->weight);
q=q->next;
}
return 0;
*/
while(root->next!=NULL)
{
p=(Node)malloc(sizeof(node));
p->next=NULL;
p->lchild=root;
p->rchild=root->next;
p->weight=root->weight + root->next->weight;
root=insert_2(p);
}
inorder(root);
// preorder(root);
transform(root);
fclose(in);
in=fopen("D:\\test.txt","r");
while(1)
{
ch=fgetc(in);
if(ch=='\n')
continue;
if(ch==EOF)
{
ch=0;
}
//printf("%s",pw[ch]);
strcat(sup,pw[ch]);
if(ch==0)
break;
}
int l=strlen(sup);
int sum;
for(i=0; i<l; i+=8)
{
if(i+8<l)
{
sum=0;
for(j=i,k=7; j<i+8; j++,k--)
{
fprintf(out,"%c",sup[j]);
sum+=pow(2,k)*(sup[j]-'0');
}
printf("%x",sum);
}
else
{
sum=0;
for(j=i,k=7; j<l; j++,k--)
{
fprintf(out,"%c",sup[j]);
sum+=pow(2,k)*(sup[j]-'0');
}
printf("%x",sum);
for(j=l; j<i+8; j++)
fprintf(out,"%c",'0');
}
}
fclose(in);
fclose(out);
}