您的位置:首页 > 编程语言 > C语言/C++

设计hafuman 编码器与解码器 C++实现

2012-04-20 13:11 330 查看
这是本人在本科阶段的哈弗曼树的代码实现。设计hafuman 编码器与解码器

问题描述:利用哈夫曼编码进行信息通讯可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传输数据预先编码;在接受端将传来的数据进行译码。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个哈夫曼码的编/译码系统。

基本要求:根据某字符文件统计字符出现频度,构造Huffman 树,编制Huffman编码,并将给定字符文件编码,生成编码文件;再将给定编码文件解码,生成字符文件。(要求按二进制位表示编码)英文文件。用二进制表示编码,生成二进制的编码文件。





#pragma once
#ifndef HUFFMAN_H
#define HUFFMAN_H
#include <iostream>
#include <string>
using namespace std;
//................  .h文件............
class node // 存放字符和字符频率类
{
public:
       intsign;
       charch;
       intfrequence;
       node():frequence(0),sign(0){}
       node(charx,int f=0){ch=x;frequence=f;}
       node&operator =(const node& n){ch=n.ch;frequence=n.frequence;return *this;}
};
 
 
 
//--------------------------------------------------以下是编码类-------------------------------------
 
class hufftree;
 
class huffnode
{friend class hufftree;
public:
       huffnode*next,*leftchild,*rightchild,*parent;
       intcode[100]; //.......存放编码....................//
       intdata; //..............权值.......................//
       charch; //字符//
       huffnode(huffnode*pnext=NULL,huffnode*left=NULL,huffnode*right=NULL)
       {next=pnext;leftchild=left;rightchild=right;
       }//..........数据成员初始花..........//
 
 
       huffnode(intitem,char a,huffnode *pnext=NULL,huffnode*left=NULL,huffnode*right=NULL)
       {data=item;ch=a;next=pnext;leftchild=left;rightchild=right;}
};
 
 
class hufftree
{
 
public:
       nodearray[100]; //.........存放单一字符对象数组.......................//
       huffnode*head,*huffroot;
       hufftree();
       voidInsert(int x,char a); //................插入...................//
       voidconnect(huffnode *p); //.....将接点链成单链表........//
       huffnode* Min();///......................求频率最小的那个接点
       voidFrequence(char line[]);//// 求每个字符的频率
       voidSethufftree();//..................造树problem.......................
       voidInorder(huffnode *r);//?????????
       voidoutput();//-------------------------------------输出函数---
       voiddelet(huffnode * p); //...........................断开指针,没有删除----------
       voidhuffcode(); // 构造huffman编码
       voidoutputcode();//-----------------------------------------------输出编码-----------
       voidsortcode(); //............输出编码信息
       voidIncode(char cha[]); //信息封装//
       voidtranscode(); // 进行译码
 
};
#endif
 
 
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
//#include "stdafx.h"
#include "huffman.h"
#include <iostream>
#include <fstream>
using namespace std;
extern int number;//..........输入字符长度................//
extern int a[100]; //....存放输入字符文件编码数组......//
extern int maxsize;//........输入字符文件编码长度.............//
int count; // 用来记录单一字符的长度
 
int len(char ch[])// 用来求字符串的长度
{
       inti(0),num(0);
       while(ch[i]!=NULL)
       {
              num++;
              i++;
       }
       number=num;
       returnnum;
}
 
hufftree::hufftree() //
{huffnode *newnode=new huffnode();
head=newnode;
head->next=NULL;
}
 
 
void hufftree::Insert(int x,chara)//===--------------------------插入函数-------------------------
{
       huffnode*p,*pre;
       p=head->next;
       if(p==NULL)
       {
              huffnode*newnode=new huffnode(x,a,NULL,NULL,NULL);
              head->next=newnode;
              huffroot=newnode;
 
       }
       else
       {// huffnode(int item,char a,huffnode*pnext=NULL,huffnode*left=NULL,huffnode*right=NULL)
              //{data=item;ch=a;next=pnext;leftchild=left;rightchild=right;}
              huffnode*newnode=new huffnode(x,a,NULL,NULL,NULL);
              while(p)
              {
                     pre=p;
                     p=p->next;
              }
              pre->next=newnode;
              huffroot=newnode;
       }
 
}
 
 
void hufftree::connect(huffnode *p) // 将哈夫曼树树的叶子结点链成一个单链表(尾插法)
{
       huffnode*t=head,*pre;
       while(t)
       {
              pre=t;
              t=t->next;
       }
       pre->next=p;
       p->next=NULL;
}
 
 
huffnode *hufftree:: Min()///-------------------------------求频率最小的那个接点
{
       if(head->next==NULL)
       {cout<<"文件为空!.."<<endl;
       returnNULL;}
       else
       {
 
              intmin=1000;
              huffnode*p=head->next;
              huffnode*t;
              while(p!=NULL)
              {
                     if(min>p->data)
                     {
                            min=p->data;
                            t=p;
 
                     }
                     p=p->next;
              }
              delet(t);//.......每次找到最小的接点后断开...........//
              returnt;
       }
 
}
 
 
void hufftree::Frequence(char line[])//// 求每个字符的频率
{
      
char ch[100];
for(int x=0;x<len(ch);x++)//.....len(ch)=number..........//
{
ch[x]=line[x];
}
int j(0),length(0);
int i,k;
 
int size=len(ch);
 
for(k=0;k<size;k++)
{
if(ch[k]!=NULL)
{
array[j].ch=ch[k]; //.......存放单一字符并统计频率.................//
for( i=0;i<size;i++)
{
if(ch[i]!=NULL)
{
if(array[j].ch==ch[i])
{
++array[j].frequence;
ch[i]=NULL;                                                                 
}
}
}
j++;
}
}
length=j;
count=length;
//cout<<"length="<<length<<endl;
/*for(i=0;i<length;i++)
{
cout<<"The"<<i<<"thchar is "<<array[i].ch<<" The frequence is"<<array[i].frequence<<endl;
 
} */
 
}
 
 
voidhufftree::Sethufftree()//-------------------------------建哈夫曼树--------------------------------------
{
       huffnode*pt=head->next;
       while(pt)
       {
              huffnode*p=Min();
              huffnode*t=Min();
              if(t==NULL)//最后一个接点//
              {
                     Insert((p->data),NULL);
              }
 
              else
              {
                     Insert((p->data+t->data),NULL);
              }
              huffroot->leftchild=p;
              huffroot->rightchild=t;
              p->parent=huffroot;
              if(t!=NULL)
              {
                     t->parent=huffroot;
              }
              pt=head->next->next;
              if(pt==NULL)
              {
                     huffroot->parent=pt;
                     head->next=NULL;
              }
       }
}
 
//------------------------哈夫蔓树的中序遍历建立单连表-------------------
void hufftree::Inorder(huffnode *r)
 
{
       if(r!=NULL)
       {
              Inorder(r->leftchild);
              //cout<<r->data;
              if(r->leftchild==NULL&& r->rightchild==NULL)
              {
 
 
                     connect(r);
 
                     //cout<<r->ch;
              }
              Inorder(r->rightchild);
       }
}
 
//.....................-输出函数.................................//
void hufftree::output()
{
       huffnode*p=head->next;//头接点
       while(p)
       {
              cout<<p->ch <<" " <<p->data <<endl;
              p=p->next;
       }
}
 
 
void hufftree::delet(huffnode * p)//----------------------断开指针-------------
{
       huffnode*t=head->next,*pre=head;
       if(t==NULL){cout<<"All of the elements have been deleted!.."<<endl;exit(1);}
       else
       {
              while(t!=p)
              {
                     pre=t;    
                     t=t->next;
              }
              pre->next=p->next;
       }
}
 
 
void hufftree::huffcode() // 构造huffman编码
{
       huffnode*p=head->next,*t;
 
       while(p!=NULL)//........遍历单连表(叶子结点).............//
       {int i=99;
       t=p;//???????
       while(t->parent!=NULL)//..........将每个叶子结点的编码放到结点数组.....................//
       {
              if(t->parent->leftchild==t)
              {
                     p->code[i]=0;
                     i--;
              }
              else
              {
                     p->code[i]=1;
                     i--;
              }
              t=t->parent;
       }
       p=p->next;
 
       }
 
}
 
voidhufftree::outputcode()//----------------------输出编码每个字符的编码--------------------
{
       huffnode*p=head->next;
       intj(0);
       while(p)
       {
              //cout<<"\nThe char " <<p->ch <<" 's huffman codeis ";
              for(inti=0;i <100;i++)
              {
                     if(p->code[i]==0|| p->code[i]==1)
                     {
                            //cout<<p->code[i];
                            a[j]=p->code[i];//.......将开始输入的字符编码放到一个数组..............//
                            j++;
                     }
              }
              p=p->next;
       }
       maxsize=j;//....a[i]字符编码的最大值.....//
}
 
 
 
void hufftree::sortcode() //............输出编码信息
{ cout<<"编码后信息为:"<<endl;
ofstreamoutfile2("file2.txt",ios::binary);
if(!outfile2)
{cout<<"open file2.txterror!"<<endl;
exit(1);
}
 
 
for(int m=0;m<count;m++)
{
       huffnode*p=head->next; //单链表//
       while(p)
       {
              if(array[m].ch==p->ch)
              {
                     //cout<<"\nThechar "<<p->ch<<" 's huffman code is ";
                     for(inti=0;i<100;i++)
                     {
                            if(p->code[i]==0|| p->code[i]==1)
                            {
                    
                            outfile2.write((char*)&p->code[i],sizeof(p->code[i]));     
 
                            }
                     }
              }
              p=p->next;
       }
}
outfile2.close();
 
ifstreaminfile2("file2.txt",ios::in|ios::binary);
if(!infile2)
{cout<<"open file2.txterror!"<<endl;
exit(1);
}
infile2.read("file2.txt",100 );
 
while(p)
{cout<<p->code[i]}
infile2.close();*/
 
cout<<endl;
}
 
 
 
void hufftree::Incode(char cha[]) //信息封装//
{
       intj=0;
       //cout<<"NUmber " <<len(cha) <<endl;
       /*for(intk=0;k <number;k++) //输出编码//
       {
       cout<<cha[k];
 
       }*/
       for(intm=0;m <number;m++)
       {
              huffnode*p=head->next;
              while(p)
              {
 
                     if(cha[m]==p->ch)
                     {
                            //cout<<"\nThe char " <<p->ch <<" 's huffman codeis ";
                            for(inti=0;i <100;i++)
                            {
                                   if(p->code[i]==0|| p->code[i]==1)
                                   {
                                          //cout<<p->code[i];
                                          a[j]=p->code[i];//........将开始输入的字符文件编码存入数组中.....................//
                                          j++;
                                   }
                            }
                     }
                     p=p->next;
              }
       }
       maxsize=j;
 
}
 
 
void hufftree::transcode() // 进行译码
{
       ofstreamoutfile3("file3.txt");
if(!outfile3)
{cout <<"open file3.txterror!" <<endl;
exit(1);}
 
huffnode *p=huffroot; //哈夫曼树//
int i=0;
cout <<"译码后信息为: ";
while(p)
{
       if(a[i]==0)
              p=p->leftchild;
       else
              p=p->rightchild;
 
       if(p->leftchild==NULL&& p->rightchild==NULL)
       {
              //cout<<p->ch;
              outfile3.put(p->ch);
              p=huffroot;//.........返回哈夫树根接点.............//
       } 
 
       i++;
       if(i>=maxsize)
              break;
}
outfile3.close();
ifstreaminfile3("file3.txt",ios::in);
char c;
if(!infile3)
cout <<"open error!"<<endl;
while(infile3.get(c))
cout <<c;
infile3.close();
 
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//....................main().................
//#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include"huffman.h"
using namespace std;
 
int number=0; //存放字符串的长度
int a[100]; // 用来存放编码的数组
int maxsize=0; // 用来记录编码的长度
 
extern int count; // 用来记录字符的长度
 
hufftree list ;
       charch[100];
     
void qidong()
{     inti;ifstream infile("file1.txt",ios::in);
if(!infile)
              {cout<<"open file1.txt error!" <<endl;
              exit(1);
              }
       for(i=0;i<100;i++)
       {     infile>>ch[i];
if((ch[i]==' ')&&(ch[i+1]==' '))
       break;}
              infile.close();
 
}
void display()
{
       for(int i=0;i <count;i++)
       {
              list.Insert(list.array[i].frequence,list.array[i].ch);//.......将字符链成链表.......//
       }
}
 
 
int main()
{ 
   char op;
       intflag=1;
       while(flag)
       {cout<<endl <<"请选择:" <<endl;
       cout<<"        菜单            " <<endl;
       cout<<"1__启动要编码文件"<<endl;
       cout<<"2__编码            " <<endl;
       cout<<"3__输出解码后的文件"<<endl;
       cout<<"4__退出程序"<<endl;
       cout<<endl;
       cin>>op;
       switch(op)
       {
       case'1':
              cout<<"请启动要编码的文件:"<<endl;
      
 
              qidong();//...................调用字符文件..........//
              list.Frequence(ch);//.........求每个字符的频率 ........//
              display();
//list.output();
 
              break;
 
       case'2':
              cout<<"对文件进行编码:"<<endl;
              list.Sethufftree();//............建哈夫曼树......................//
              list.Inorder(list.huffroot);//.........叶子结点链成单链表...............//
              //list.output();
              list.huffcode();//.........构造huffman编码.......//
              list.sortcode();  //.............输出编码............//
              break;
 
 
       case'3':
              cout<<"编码后的文件为:"<<endl;
              list.Incode(ch);//编译字符文件对应码的信息//
              list.transcode();//.......输出译码信息...........//
              cout<<endl;
              break;
 
             
       case'4':
              flag=0;
              cout<< "程序结束,按任意键退出"<<endl;
              break;
       default:
              cout<<"输入错误,请重新输入!"<<endl;
       }
       }
 
       system("pause");
       return0;
}


欢迎 各位拍砖!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: