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

📄 哈夫曼1编码.txt

📁 哈夫曼编码译码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
哈夫曼编码/译码
一、【实验内容】
【问题描述】
      利用哈夫曼编码进行住处通讯可以大大提高信道利用率,缩短住处传输时间,降低成本,但是,这要求在发送端通过一个编码系统将传输的数据预先编码,在接收端通过一个译码系统对传来的数据进行译码(复原),对于双向传输信息的信道,每端都一个完整的编码译码系统,试为这样的住处收发站写一个哈夫曼友的编码译码系统.

【基本要求】:一个完整的系统应以下功能:
(1) I. 初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存放在文件hfmTree中.
(2) E. 编码(Encoding)。利用已建立好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果代码存(传输)到文件CodeFile中.
(3) D. 译码(Decoding)。利用已建好的哈夫曼树,对传输到达的CodeFile中的数据代码进行译码,将译码结果存入文件TextFile中. 
(4) P. 印文件代码(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。 
(5) T. 印哈夫曼树(TreePrinting)。将已在内存中的哈夫曼树以直观的方式(树或凹入表的形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
      
测试数据:
(1) 利用教科书例6-2中的数据调试程序。
(2) 用下表给出的字符集和频度的计数据建立哈曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”.。
字符       A   B    C    D    E    F    G    H    I    J    K    L    M
频数 186  64   13   22   32   103  21   15   47   57   1    5    32   20
字符 N    O    P    Q    R    S    T    U    V    W    X    Y    Z
频数 57   63   15   1    48   51   80   23   8    18   1    16   1 


二、实验目的
树型结构是一种应用极为广泛的非线性数据结构,也是本课程的重点内容,哈夫曼树(最优二叉树)是树型结构的典型应用,本次实验突出了数据结构加操作的程序设计观点,希望能根据树型结构的非线性特点,熟悉各种存储结构的特性,达到如何应用树型结构的非线性特点,熟悉各种存储结构的特性,达到如何应用树型结构解决具体问题的目的.

 

 


三、实验文档:
                  哈夫曼编码/译码
一、 需求分析
1、 利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时
间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。本次设计就是为这样的信息收发站写的一个哈夫曼的编/译码器。
本实验要求:
2、本演示程序中,用户可以输入键盘中的任意字符,长度为任意长,字符输入顺序不限,且允许出现重码
3、演示程序以用户与计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令,相应的输入数据(可虑去输入中的非法字符)和运算结果显示在其后。
4、本演示程序中,当用户选择的功能错误时,系统会输出相应的提示。
5、在本系统中,用户可以对任意长的字符串可进行编码/译码。
6、程序执行的命令包括:
 1) 初始化(I)   2) 编码(E)    3) 译码(D) 
4) 印代码文件(P) 5) 印哈夫曼树(T) 6) 退出(Q)
7、测试数据:
  (1)利用教科书例6-2中的数据调试程序。
(2)用下表给出的字符集和频度的计数据建立哈曼树,并实现以下报文的
   编码和译码:“THIS PROGRAM IS MY FAVORITE”.。
字符     A   B   C   D   E   F   G   H   I   J   K   L   M
频数 186  64    13    22    32   103    21   15   47    57    1    5     32    20
字符 N  O   P   Q   R    S    T   U    V   W   X    Y   Z
频数 57   63    15    1    48     51     80    23     8      18    1      16    1 

二、概要设计
为实现上述程序功能,应以指针存储结点。为此,需要定义一个抽象数据类型。
1. 抽象数据类型定义为:
ADT HuffmanTree{
数据对象:D={ai| ai∈CharSet,i=1,2,……,n,  n≥0}
数据关系:R={< ai-1, ai > ai-1, ai∈D, ai-1<ai ,i=2,3,……,n}
基本操作P:
HuffmanTree();       构造函数
~ HuffmanTree();     析构函数
Initialization(int WeightNum);
操作结果:构造哈夫曼树。
Encoder()
初始条件:哈夫曼树已存在或者哈夫曼树已存到文件中。
操作结果:对字符串进行编码
Decoder();
初始条件:哈夫曼树已存在且已编码。
操作结果:对二进制串进行译码
Print()
初始条件:编码文件已存在。
操作结果:把已保存好的编码文件显示在屏幕
TreePrinting()
初始条件:哈夫曼树已存在。
操作结果:将已在内存中的哈夫曼树以直观的方式显示在终端上
2.本程序包含三个模块:
1)主程序模块:
void main(){
    初始化;
do{
   接受命令;
   处理命令;
}while(“命令”=”退出”)
}
2)、建树模块――实现定义的抽象数据类型
3)、编/译码模块――实现字符串的编/译码
各模块之间的调用关系如下:
                    主程序模块
                     
                     
                      建树模块                  

                     
                     
编/译码模块
三、详细设计
程序代码如下
//        程序名:HuffmanTree.h
//      程序功能:哈夫曼树类的头文件(并用其来实现编/译码)
//          作者:刘伟高
//          日期:2006.11.27
//          版本:1.0


//对应类实现文件: HuffmanTree.cpp
//对应主程序文件: main.cpp

 

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
struct HuffmanNode        //定义哈夫曼树各结点
{
 int weight;        //存放结点的权值,假设只考虑处理权值为整数的情况
 int parent;        //记录结点父亲位置,-1表示为根结点,否则表示为非根结点
 int lchild,rchild;   //分别存放该结点的左、右孩子的所在单元的编号
};
class HuffmanTree     //建立哈夫曼树类
{
private:
 HuffmanNode *Node;      //哈夫曼树中结点的存储结构
 char *Info;           //用来保存各字符信息
 int LeafNum;          //树中的叶子结点总数
public:
 HuffmanTree();     //构造函数
 ~HuffmanTree();    //析构函数
 void Initialization(int WeightNum);   //初始化函数:根据WeightNum个权值建立一棵哈夫曼树
 void Encoder();           //编码函数:利用构造好的哈夫曼树对字符进行编码
 void Decoder();          //译码函数:对二进制串进行译码
 void Print();            //印文件函数:把已保存好的编码文件显示在屏幕
 void TreePrinting();     //印哈夫曼树函数:将已在内存中的哈夫曼树以直观的方式显示在终端上
};


//        程序名:HuffmanTree.cpp
//      程序功能:实现哈夫曼树类的源文件(并用其来实现编/译码)
//          作者:刘伟高
//          日期:2006.11.27
//          版本:1.0


#include"HuffmanTree.h"
#include<string>
using namespace std;

//////////////////////////////////////////////////////////////////////////////
//  构造函数
//  函数功能:将结点指针初始化为NULL
//  函数参数:无
//  参数返回值:无
HuffmanTree::HuffmanTree()
{
 Node=NULL;          //将树结点初始化为空 
 Info=NULL;          //将字符数组初始化为空
 LeafNum=0;          //将叶子数初始化为0
}
//////////////////////////////////////////////////////////////////////////////
// 析构函数
// 函数功能:将所有结点的空间释放
// 函数参数:无
// 参数返回值:无
HuffmanTree::~HuffmanTree()
{
 delete[] Node;         //释放结点空间
 delete[] Info;         //释放字符存储空间
}
//////////////////////////////////////////////////////////////////////////////
//  初始化函数
//  函数功能:从终端读入字符集大小n,以及n个字符和n个权值,
//            建立哈夫曼树,并将它存放在文件hfmTree中.
//  函数参数:int WeightNum表示代码个数
//  参数返回值:无 
void HuffmanTree::Initialization(int WeightNum)        //初始化
{
 int i,j,pos1,pos2,max1,max2;     //
 
 Node=new HuffmanNode[2*WeightNum-1];  //WeightNum权值对应的哈夫曼树中的结点总数为2*WeightNum-1个
 Info=new char[2*WeightNum-1];
 for(i=0;i<WeightNum;i++)
 {
  cout<<"请输入第"<<i+1<<"个字符值";
  getchar();           //丢弃字符'\t'与'\n'
  Info[i]=getchar();   //输入一个字符,主要是考虑输入空格而采用这种形式的
  getchar();
  cout<<"请输入该字符的权值或频度";
  cin>>Node[i].weight;       //输入权值
  Node[i].parent=-1;      //为根结点
  Node[i].lchild=-1;      //无左孩子
  Node[i].rchild=-1;      //无右孩子
 }
 
 for(i=WeightNum;i<2*WeightNum-1;i++) //表示需做WeightNum-1次合并
 {
  pos1=-1;
  pos2=-1;          //分别用来存放当前最小值和次小值的所在单元编号 
  max1=32767;      //32767为整型数的最大值 
  max2=32767;      //分别用来存放当前找到的最小值和次小值  

  for(j=0;j<i;j++)      //在跟节点中选出权值最小的两个
   if(Node[j].parent==-1)         //是否为根结点
    if(Node[j].weight<max1)     //是否比最小值要小
    { 
     max2=max1;            //原最小值变为次小值
     max1=Node[j].weight;      //存放最小值
     pos2=pos1;            //修改次小值所在单元编号
     pos1=j;               //修改最小值所在单元编号
    }
    else
     if(Node[j].weight<max2)     //比原最小值大但比原次小值要小
     {
      max2=Node[j].weight;     //存放次小值
      pos2=j;                  //修改次小值所在的单元编号
     }
    //for
  Node[pos1].parent=i;       //修改父亲位置
  Node[pos2].parent=i;
  Node[i].lchild=pos1;       //修改儿子位置
  Node[i].rchild=pos2;
  Node[i].parent=-1;             //表示新结点应该是根结点
  Node[i].weight=Node[pos1].weight+Node[pos2].weight;
 } //for
 LeafNum=WeightNum;
 
 
 char ch;
 cout<<"是否要替换原来文件(Y/N):";
 cin>>ch;
 if(ch=='y'||ch=='Y')
 {
 ofstream fop;   //以二进制方式打开hfmTree.dat文件,并当重新运行时覆盖原文件
 fop.open("hfmTree.dat",ios::out|ios::binary|ios::trunc);
 if(fop.fail())                     //文件打开失败
  cout<<"文件打开失败!\n";
 fop.write((char*)&WeightNum,sizeof(WeightNum));  //写入WeightNum
 for(i=0;i<WeightNum;i++)         //把各字符信息写入文件
 {
  fop.write((char*)&Info[i],sizeof(Info[i]));
  flush(cout);
 }
 for(i=0;i<2*WeightNum-1;i++)        //把个节点内容写入文件
 {
  fop.write((char*)&Node[i],sizeof(Node[i]));
  flush(cout);
 }
 fop.close();            //关闭文件
 }
 cout<<"哈夫曼树已构造完成。\n";
}//Initialization

//////////////////////////////////////////////////////////////////////////////
//  编码函数
//  函数功能:利用已建立好的哈夫曼树(如不在内存,则从文件hfmTree中读入),
//            对文件ToBeTran中的正文进行编码,然后将结果代码存(传输)到文件CodeFile中.
//  函数参数:无
//  参数返回值:无
void HuffmanTree::Encoder()
{
 if(Node==NULL)       //哈夫曼树不在内存,从文件hfmTree中读入
 {
  ifstream fip;        //以二进制方式打开hfmTree.dat文件
  fip.open("hfmTree.dat",ios::binary|ios::in);
  if(fip.fail())       //文件打开失败
  {
   cout<<"文件打开失败!\n";
   return;          //结束本函数
  }
  fip.read((char*)&LeafNum,sizeof(LeafNum));  //读取叶子数
  Info=new char[LeafNum]; 
  Node=new HuffmanNode[2*LeafNum-1];
  for(int i=0;i<LeafNum;i++)              //读取字符信息
   fip.read((char*)&Info[i],sizeof(Info[i]));
  for(i=0;i<2*LeafNum-1;i++)              //读取结点信息
   fip.read((char*)&Node[i],sizeof(Node[i]));
 }
 
 char *Tree;          //用于存储需编码内容
 int i=0,num;
 char Choose;         //让用户选择读取文件或重新输入需编码内容
 cout<<"你要从文件中读取内容(1),还是重新输入(2):";
 cin>>Choose;
 if(Choose=='1')          //读取文件ToBeTran.txt
 {
  ifstream fip1("ToBeTran.txt");
  if(fip1.fail())      //文件不存在
  {
   cout<<"文件打开失败!\n";
   return;          //结束本函数
  }
  char ch;
  int k=0;
  while(fip1.get(ch))            
  {
   k++;                     //计算CodeFile中代码长度
  } 
  fip1.close();  
 
  Tree=new char[k+1];
  ifstream fip2("ToBeTran.txt");

  k=0; 
  while(fip2.get(ch))
  {
   Tree[k]=ch;           //读取文件内容,并存到Tree中
   k++;
  }
  fip2.close();

⌨️ 快捷键说明

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