⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffman.cpp

📁 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 + -