📄 huffman.cpp
字号:
#include<iostream.h>
#include<iomanip.h>
#include<stdio.h>
#define NUM 256 //字母数
#define TNUM 511 // 总结点数为num+(num-1)
#define CLONG 24 //编码最大长度
class Node
{
public:
int data; // byte will be converted to int
long weight;
int parent;
int lchild;
int rchild;
};
void main()
{
long weight[NUM];//256个字符出现频率
int nzc=0; //the count of symbol with no zero weight
long maxweight; // 最大字节数,根的权
int maxclength=0,minclength=100; //码表中最长的码
int i,j,smallest,small;
long smallestw,smallw;
int hcode[NUM][CLONG]; //用于存储编码
int son,father;
char codetable[256][5]; //码表 0 长度 1 2 3 为码 4 为代表的symbol
FILE *source,*destination;
Node nodes[TNUM]; //用对象数组存储哈夫曼树
for(i=0;i<NUM;i++){
nodes[i].data=257;
nodes[i].weight=0;
nodes[i].lchild=-1;
nodes[i].rchild=-1;
nodes[i].parent=-1;
}
// read the source file and count the weight
for(i=0;i<NUM;i++){
weight[i]=0;
}
/////////////////////////////////////////////////////////////////////////////
if((source=fopen("compress.txt","w"))==NULL)
{
printf("source file can not be opened!\n");
return;
}
for(i=0;i<256;i++){fputc((char)i,source);}
maxweight=ftell(source);
fclose(source);
////////////////////////////////////////////////////////////////////////////////
if((source=fopen("compress.txt","r"))==NULL)
{
printf("source file can not be opened!\n");
return;
}
while(!feof(source)){
weight[(int)(fgetc(source))]++;
}
maxweight=ftell(source);
fclose(source);
//
nzc=0;
for(i=0;i<NUM;i++)
{
if(weight[i]!=0)
{
nodes[nzc].data=i;
nodes[nzc].weight=weight[i];
nzc++;
}
}
///now nodes[i] contain only valid value;
for(i=nzc;i<2*nzc-1;i++)
{
nodes[i].data=257; //其实不是什么真正的字符
nodes[i].weight=-1;
nodes[i].parent=-1;
nodes[i].lchild=-1;
nodes[i].rchild=-1;
}
//建立哈夫曼树
for(i=nzc;i<2*nzc-1;i++)
{
smallest=small=-1; //权数最小的两个节点
smallestw=smallw=maxweight; //代表有最小的权数的节点的权
for(j=0;j<i;j++)
{
if(nodes[j].parent==-1)
{
if(nodes[j].weight<smallestw)
{
smallw=smallestw;
smallestw=nodes[j].weight;
small=smallest;
smallest=j;
}
else if(nodes[j].weight>smallestw&&nodes[j].weight<smallw)
{
smallw=nodes[j].weight;
small=j;
}
}
}//for语句得到 parent=-1(即尚没有父结点)且weight最小的两个结点
nodes[small].parent=i;
nodes[smallest].parent=i;
nodes[i].lchild=small;
nodes[i].rchild=smallest;
nodes[i].weight=nodes[smallest].weight+nodes[small].weight;
}
//到此就完成了树
//初始化huffman code
for(i=0;i<nzc;i++)
{
for(j=0;j<CLONG;j++)
{
hcode[i][j]=3; // any digital will be ok except of '1'and'0'
}
}
//编码 开始
for(i=0;i<nzc;i++)
{
j=CLONG-1; ///从高位向下存
for(son=i,father=nodes[i].parent;father!=-1;) // 一定要注意判断条件。
{
if(nodes[father].lchild==son)
{
hcode[i][j]=1;
}
else
{
hcode[i][j]=0;
}
j--;
son=father,father=nodes[son].parent;
}
}
// 编码成功 下面创建码表
int length;
int m,n;
for(i=0;i<nzc;i++){
length=0;
for(j=0;j<CLONG;j++)
{
if (hcode[i][j]!=3) length++;
}
m=7;n=1;
codetable[i][1]=(char)0;
codetable[i][2]=(char)0;
codetable[i][3]=(char)0;
for(j=CLONG-length;j<CLONG;j++){
if(hcode[i][j]==1){
codetable[i][n]=(char)( codetable[i][n]|(char)(1<<m));
}
m--;
if(m==-1){
n++;
m=7;
}
}
if (length>maxclength)
{maxclength=length;}
if(length<minclength)
{minclength=length;}
codetable[i][0]=(char)length; // 码表每个下标代表symbol,每个item第一个字节为长度
codetable[i][4]=(char)nodes[i].data;
}
if((destination=fopen("codetable.txt","w"))==NULL)
{
printf("source file can not be opened!\n");
return;
}
for(i=0;i<nzc;i++){
fputc(codetable[i][0],destination);
fputc(codetable[i][1],destination);
fputc(codetable[i][2],destination);
fputc(codetable[i][3],destination);
fputc(codetable[i][4],destination);
}
fclose(destination);
// 特别说明:nodes里面从0到nzc-1都是有效的。
//输出 nodes
/*
cout<<"HuffmanTree:"<<endl;
cout<<setw(4)<<"NO."<<setw(6)<<"data"<<setw(8)<<"weight"<<setw(6)
<<"parnt"<<setw(6)<<"lchd"<<setw(6)<<"rchd"<<endl;
for(i=0;i<TNUM;i++)
{
cout<<setw(4)<<i<<setw(6)<<nodes[i].data<<setw(8)<<nodes[i].weight<<setw(6)
<<nodes[i].parent<<setw(6)<<nodes[i].lchild<<setw(6)<<nodes[i].rchild<<endl;
}
*/
//输出编码
cout<<"maxlength"<<maxclength<<"minlength"<<minclength<<endl;
cout<<"from table \n";
i=1;
cout<<"NO."<<i<<":L"<<(int)codetable[i][0]<<":char"<<(int)codetable[i][1]<<(int)codetable[i][2]<<(int)codetable[i][3]<<" "<<(int)codetable[i][4];
/*
if((destination=fopen("char.txt","w"))==NULL)
{
printf("source file can not be opened!\n");
return;
}
fputc(codetable[0][1],destination);
fputc(codetable[0][2],destination);
fputc(codetable[0][3],destination);
fclose(destination);
*/
cout<<"共有"<<nzc<<"个不是0的";
cout<<endl<<"Result:"<<endl;
cout<<setw(6)<<"symbol"<<setw(10)<<"frequency"<<setw(16)<<"huffmancode\n";
for(i=0;i<nzc;i++)
{
cout<<setw(6)<<nodes[i].data<<setw(10)<<nodes[i].weight; cout<<" ";
for(j=0;j<CLONG;j++)
{
if(hcode[i][j]!=3)
{
cout<<hcode[i][j];
}
}
cout<<endl;
}
cout<<"\nDone"<<endl;
cout<<"共有"<<nzc<<"个不是0的";
for(i=0;i<nzc;i++)
{
cout<<nodes[i].data<<" ";
}
cout<<maxweight;
cout<<"done!";
getchar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -