哈夫曼树的编码实现

来源:互联网 发布:按键精灵软件 编辑:程序博客网 时间:2024/05/17 21:33
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>  
using namespace std;
typedef struct{
  char data;
  int weight;
  int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
void Select(HuffmanTree &HT,int n,int m) 
{
  HuffmanTree p=HT;
  int tmp;
  for(int j=n+1;j<=m;j++)
  {
       int tag1,tag2,s1,s2;
       tag1=tag2=256;
  for(int x=1;x<=j-1;x++)  
  { 
       if(p[x].parent==0&&p[x].weight<tag1)
{
  tag1=p[x].weight;
  s1=x;
}  
  }
       for(int y=1;y<=j-1;y++)
       {   
           if(p[y].parent==0&&y!=s1&&p[y].weight<tag2)
  { 
   tag2=p[y].weight;
s2=y;
}
       }
if(s1>s2)  //将选出的两个节点中的序号较小的始终赋给s1
{
  tmp=s1;
  s1=s2;
  s2=tmp;
}
    p[s1].parent=j;
p[s2].parent=j;
p[j].lchild=s1;
p[j].rchild=s2;
p[j].weight=p[s1].weight+p[s2].weight;
  }
}
void HuffmanCoding(HuffmanTree &HT,int n,char *w1,int*w2)
{  
   int m=2*n-1;
   if(n<=1)   return;
   HT=new HTNode[m+1];
   HuffmanTree p=HT;
   for(int i=1;i<=m;i++)
   { 
       p[i].weight=p[i].parent=p[i].lchild=p[i].rchild=0; 
   }
   for(int i=1;i<=n;i++)
   {
       p[i].data=w1[i-1];
  p[i].weight=w2[i];
       p[i].parent=p[i].lchild=p[i].rchild=0;
   }
  
  Select(HT,n,m);
  ofstream outfile("hfmTree.txt");        //生成hfmTree文件
  for (int i=1;i<=m;i++)
  {
     outfile<<HT[i].weight<<"\t"<<HT[i].parent<<"\t"<<HT[i].lchild
     <<"\t"<<HT[i].rchild<<"\t"<<endl;
   }
   outfile.close();
   cout<<"初始化结果已保存在hfmTree文件中\n";
}
void ToBeTree()            //将正文写入文件ToBeTree中
{
ofstream outfile("ToBeTree.txt");
outfile<<"THIS PROGRAM IS MYFAVORITE";
outfile.close();
}
void Encoding(HuffmanTree &HT,int n)    //编码
 {
    HuffmanCode HC;
    HC=new char*[n+1];//分配储存n个字符编码的编码表空间 
    char *cd;
    cd=new char[n];//分配临时存放每个字符编码的动态数组空间 
    cd[n-1]='\0';//编码结束 
    for(int i=1;i<=n;i++)//逐个字符求哈夫曼编码 
    {
  int start=n-1;//start开始时指向最后,即编码结束位置 
  int c=i;
  int f=HT[i].parent;//f指向结点c的双亲结点 
  while(f!=0)
       {
     if(HT[f].lchild==c)
     cd[--start]='0';//结点c是f的左孩子,即生成代码0 
     else
     cd[--start]='1';//结点c是f的右孩子,即生成代码1 
     c=f;
     f=HT[f].parent;//继续向上回溯 
  }//求出第i个字符的编码 
  HC[i]=new char[n-start];//为第i个字符编码分配空间 
  strcpy(HC[i],&cd[start]);//将求得的编码从临时空间cd复制到HC的当前行中 
  } 
  delete cd;//释放临时空间 
  cout<<"输出哈夫曼编码:"<<endl;  
  for(int h=1;h<=n;h++)           //输出编码
  {   cout<<HT[h].data<<":";
      cout<<HC[h];
      cout<<"  ";
     if (h%8==0)
cout<<endl;
  }
   cout<<endl<<"输出正文编码:"<<endl;
   ToBeTree();
  //读取TOBETREE文件里的正文,并进行编码
   fstream infile("ToBeTree.txt");


   char s[80];
   while(!infile.eof())//判断是否到达文件尾部,以防止出现文件读取错误。
   {
      infile.getline(s,sizeof(s));
}
    infile.close();
    fstream outfile("CodeFile.txt",ios::out);
    int count=0;
    for (int h=0;s[h]!='\0';h++)
    {
    for(int k=1;k<=n;k++)
        if (s[h]==HT[k].data)
   {
      cout<<HC[k];
           cout<<" ";
      count++;
      outfile<<HC[k];
           break;
   }
        if (count%9==0)
   cout<<endl;     //每输出7个换行
}
    outfile.close();
    cout<<"\n编码结果已保存在文件CodeFile中.";
    cout<<endl;
}
void Decoding(HuffmanTree &HT,int n)   //译码
{
   int f=2*n-1;
   fstream infile("CodeFile.txt");


   char s[1000];
   while(!infile.eof())
   {
      infile.getline(s,sizeof(s));
   }
   infile.close();
   int i=0;
   int j=0;
   fstream outfile("TextFile.txt",ios::out);


   while(s[i]!='\0')
   {
      f=2*n-1;
      while(HT[f].lchild!=0)//以f对应的节点的左孩子的值==0作为结束
 {
     if (s[j]=='0')
     f=HT[f].lchild;
 else 
 f=HT[f].rchild;
 j++;
 }  
 i=j;
 cout<<HT[f].data;
 outfile<<HT[f].data; 
    }
    outfile.close();
    cout<<"\n译码结果已保存在文件TextFile中.";
    cout<<endl;
}
void Print()          //印代码文件
{
    int count=0;
fstream infile("CodeFile.txt");
    
char s[1000];
while(!infile.eof())
{
   infile.getline(s,sizeof(s));
   for(int i=0;s[i]!='\0';i++)
   {
  cout<<s[i];
  count++;
  if (count%50==0)  cout<<endl; //在终端上每行显示50个代码
   }
}
    infile.close();
cout<<endl;
}
char menu()              //菜单函数
{
     cout<<"功能菜单如下:"<<endl;
cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl;
     cout<<"*       1:初始化(Initialization)        *"<<endl;
cout<<"*       2:编码(Encoding)                *"<<endl;
     cout<<"*       3:译码(Decoding)                *"<<endl;
     cout<<"*       4:印代码文件(Print)             *"<<endl;
     cout<<"*       0:退出(Exit)                    *"<<endl;
cout<<"* * * * * * * * * * * * * * * * * * * * *"<<endl;
cout<<"请输入功能字符:";
int n;
cin>>n;
     return n;
}
int main()
{  
   int n;
   int Array[100];
   char cArray[100];
   HuffmanTree HT;
   cout<<"输入n个字符:";
   cin.getline(cArray,100);
   n=strlen(cArray);
   cout<<"一共"<<n<<"个字符.\n";
   cout<<"依次输入各个字符的权值:"<<endl;
   for (int i=1;i<=n;i++)
   cin>>Array[i];
   int tag;
   int x=menu();
   while(1)
   {
      switch (x)  
      {
          case 1:HuffmanCoding(HT,n,cArray,Array);
          break;
          case 2:Encoding(HT,n);
          break;
          case 3:Decoding(HT,n);
          break;
          case 4:Print();
          break;
          case 0:
          cout<<"结束"<<endl;
  exit(0);   
          default:cout<<"你输入错误!"<<endl;   
      }
      cout<<"请输入功能字符:"; 
     cin>>x;  
    }
1 0
原创粉丝点击