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

📄 haffman.h

📁 哈夫曼的编译码问题
💻 H
字号:
typedef struct
{
    
	int weight;
	int flag;
	int parent;
	int leftchild;
	int rightchild;
}HaffNode;
typedef struct
{
	char str;
	int bit[Max];
	int start;
	int weight;
}Code;
class Haffman
{
private:
    HaffNode haffTree[2*Max];//哈夫曼树
	int leaf;//有多少个叶子结点
	Code haffCode[Max];//
	int grand;
public:
    Haffman();//构造哈夫曼树
	void HaffManC();//写编码
	void HaffCodeD();
    int Get(){return grand;}
    void HaffCodeT(int,int);
	void HaffCodeP();
};

 Haffman::Haffman ()
{
	char ch;
    int i,k,h,m1,m2,x1,x2,j;
	for(j=0;j<2*Max;j++)
		haffTree[j].weight=0;
	i=0;
    ifstream infile("file.txt");
   if(!infile)
   {
	  cout<<"can't open file"<<endl;
	  abort();//-----------退出程序
   }
   //------------从文件file.txt中把字符依次读入,并统计每 个字体符出现的次数即是它们的权值,
   //-------每出现一个新的字符就把它存到数组haffcode中,如果以前已经出现了就在该字符的权值下加一 
	while(infile>>ch)
    {
		for(k=0;k<i;k++)
			if(haffCode[k].str==ch)break;
	    if(k==i){
		haffCode[i].str=ch;
		haffTree[i].weight++;
		i++;
			}
		else haffTree[k].weight++;
	}
	//---------最后HAFFCODE的数组的长度即统计的字符的个数即是叶子结点的个数 
	leaf=i;
	cout<<"leaf="<<leaf<<endl; 
	//-----------起初把左右孩子结点及双亲都赋为空 
    for(i=0;i<2*leaf-1;i++)
	{
	haffTree[i].parent=-1;
	haffTree[i].leftchild=-1;
	haffTree[i].rightchild=-1;
	haffTree[i].flag=0;//----------标记有处于挑出两个孩子结点
	}
	//-----------构造哈夫曼树,找出叶子结点的双亲结点并一直到主根 
	//-----------确定每个根的左右孩子结点 
    for(i=0;i<leaf-1;i++)
	{
		m1=m2=MaxValue;//------把权值都设为最大的
		x1=x2=0;//------把下标都设为零
		for(j=0;j<leaf+i;j++)//-------找出下标为N+I的两个孩子结点,即在0和N+I中挑两个最小的
        {
			if(haffTree[j].weight<m1&&haffTree[j].flag==0)
			{
				m2=m1;
				x2=x1;
				m1=haffTree[j].weight;
				x1=j;
			}//--------x1的权值始终小于等于X2
			else if(haffTree[j].weight<m2&&haffTree[j].flag==0)
			{
				m2=haffTree[j].weight;
				x2=j;
			}
		}
	
	haffTree[x1].parent=leaf+i;
	haffTree[x2].parent=leaf+i;
    haffTree[x1].flag=1;
	haffTree[x2].flag=1;
	haffTree[leaf+i].weight=haffTree[x1].weight+haffTree[x2].weight;
	haffTree[leaf+i].leftchild=x1;
	haffTree[leaf+i].rightchild=x2;
	}
}

//----------编码 
void Haffman::HaffManC()
{//------------对文件中出现的每个字符用哈夫曼编码的规则进行编码 
  Code *cd=new Code;
  int i,j,child,parent;
  char c;
  for(i=0;i<leaf;i++)
  {
	  cd->start=leaf-1;
	  cd->weight=haffTree[i].weight;
	  child=i;
	  parent=haffTree[child].parent;
	  while(parent!=-1)
	  {
		  if(haffTree[parent].leftchild==child)
			  cd->bit[cd->start]=0;
		  else cd->bit[cd->start]=1;
		   cd->start--;
		   child=parent;
		   parent=haffTree[child].parent;
	  }
	  for(j=cd->start+1;j<=leaf-1;j++)
      haffCode[i].bit[j]=cd->bit[j];
	  haffCode[i].weight=cd->weight;
	  haffCode[i].start=cd->start+1;
  }
  //----------将FILE里的字符哈夫曼编码的形式写入文本codefile文件中 
   ifstream  infile("file.txt");
    if(!infile)
	{
	  cout<<"can't open file"<<endl;
	  abort();//-----------退出程序
	} 
	ofstream out("codefile.txt");
   if(!out)
   {
	  cout<<"can't open file"<<endl;
	  abort();//-----------退出程序
   }
    while(infile>>c)
	{
		for(i=0;i<leaf;i++)
			if(c==haffCode[i].str)break;
			//cout<<i<<endl;
			for(j=haffCode[i].start;j<leaf;j++)
				out<<haffCode[i].bit[j];
	}
 out.close();
}
//---------------------译码(把文本CODEFILE中的哈夫曼编码依据哈夫曼树进行译码)
	void   Haffman::HaffCodeD()
	{
 		int i,j,a,cd,cc;
		char c;
		for(i=0;i<2*leaf-1;i++)
            if(haffTree[i].parent==-1)
			break;
		grand=i;
		ifstream in("codefile.txt");
		ofstream out("textfile.txt");
         if(!in)
		 {
	      cout<<"can't open file"<<endl;
	      abort();//-----------退出程序
		 }
		 cd=grand;//---CD的初值是主先 
		 //------每个编码从根结点开始渐渐向下逼近到叶结束,找到相应的字符再进行下一个字符的译码 
		 while(in>>c)
		 {//--------因为从文本读入的是字符,所以要转化为整型数字就要用ASCII码做变换 
			 cc=c-48;
			 if(cc==0)cd=haffTree[cd].leftchild;
			 else cd=haffTree[cd].rightchild;
			  if(haffTree[cd].leftchild==-1&&haffTree[cd].rightchild==-1)
			 {
				 out<<haffCode[cd].str;
				 cd=grand;
			 }
		 }
       out.close();
    }
    //----------以凹树的形式打印哈夫曼树 ,非叶子结点打印权值 
	void     Haffman::HaffCodeT(int a,int n)
	{
		int i;
		if(a==-1)return;
		HaffCodeT(haffTree[a].rightchild,n+1);
		for(i=0;i<n;i++)
			cout<<"      ";
        cout<<"-----";
		if(a>=0&&a<leaf)cout<<haffCode[a].str;
		cout<<"("<<haffTree[a].weight<<")";
		cout<<endl;
        HaffCodeT(haffTree[a].leftchild,n+1);
	}
//----------显示哈夫曼树每个叶结点的权值,及相应的编码
	void Haffman::HaffCodeP()
	{
		int i,j;
		for(i=0;i<leaf;i++)
		{
		cout<<haffCode[i].str<<"  "<<haffCode[i].weight<<"  ";
		for(j=haffCode[i].start;j<leaf;j++)
		cout<<haffCode[i].bit[j];
        cout<<endl;
		}
	}


			 
         


    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -