哈夫曼编译码器——数据结构课程设计

2.哈夫曼编/译码器

【问题描述】

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

【基本要求】

一个完整的系统应具有以下功能:

1I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。

2E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

3D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

4P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。

5T:印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示出,同时将此字符形式的哈夫曼树写入文件TreePrint中。

【测试数据】

(1) 用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:THIS PROGRAM IS MY FAVORITE”。

字符

A

B

C

D

E

F

G

H

I

J

K

L

M

频度

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) 编码结果以文本方式存储在文件CodeFile中。

2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”表示退出运行Quit。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。

3) 在程序的一次执行过程中,第一次执行IDC命令之后,哈夫曼树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。

//Huff.h

#include

#include

#include

#include

#include

#define MVNum 26

using namespace std;

typedef struct

{

int weight;

char data;

int parent;

int lchild;

int rchlid;

}HTNode,*HuffTree;

typedef struct

{

char data;

char *code;

}HuffmanCode[MVNum+1];

void swap(int &s1,int &s2)

{

int temp;

temp=s1;

s1=s2;

s2=temp;

}

int Select(HuffTree HT,int n,int &s1,int &s2)

{

int min1=INT_MAX,min2=INT_MAX;

for(int i=1;i<=n;i++)

{//min1>=min2;

if(HT[i].parent==0)

if(HT[i].weight

{

min1=HT[i].weight;

s1=i;

if(min1

{//保持min1>=min2

swap(min1,min2);

swap(s1,s2);

}

 

}

 

}

return 1;

}

int Initialization(HuffTree &HT,int n)

{

ofstream fout("f:\\TEMPASD\\hfmTree.dat",ios::out|ios::binary);

if(n<=1)return 0;

int m=2*n-1;

HT=new HTNode[m+1];

for(int i=0;i<=m;i++)

{

HT[i].data='#';

HT[i].parent=0;

HT[i].lchild=0;

HT[i].rchlid=0;

}

cout<<"input data&weight"<

for(int i=1;i<=n;i++)

{

cin>>HT[i].data>>HT[i].weight;

}

/*---------创建哈夫曼树-------*/

int s1,s2;

for(int i=n+1;i<=m;i++)

{

Select(HT,i-1,s1,s2);

HT[s1].parent=i;HT[s2].parent=i;

HT[i].lchild=s1;HT[i].rchlid=s2;

HT[i].weight=HT[s1].weight+HT[s2].weight;

}

fout.seekp(0,ios::beg);

for(int i=0;i<=m;i++)

{

fout.write(reinterpret_cast<char *>(&(HT[i])),sizeof(HTNode));

}

fout.close();

return 1;

}

int Initialization_1(HuffTree &HT,int n)

{

ifstream fin("f:\\TEMPASD\\hfmTree.dat",ios::in|ios::binary);

if(n<=1)return 0;

int m=2*n-1;

HT=new HTNode[m+1];

fin.seekg(0,ios::beg);

if(fin)

{

HTNode temp;

for(int i=0;i<=m;i++)

{

fin.read(reinterpret_cast<char *>(&(temp)),sizeof(HTNode));

HT[i]=temp;

}

 

}

else

{

cout<<"File could not be open"<

return 0;

}

return 1;

}

void CreateHuffmanCode(HuffTree &HT,HuffmanCode &HC,int n)

{

char *cd=new char[n];

if(HT[2*MVNum-1].lchild==0||HT[2*MVNum-1].rchlid==0)

{//内存中没有树,需重新添加

Initialization_1(HT,n);

}

cd[n-1]='\0';

for(int i=1;i<=n;i++)

{

int start=n-1;

int c=i,f=HT[i].parent;

HC[i].data=HT[i].data;

while(f!=0)

{

start--;

if(HT[f].lchild==c)

cd[start]='0';

else

cd[start]='1';

c=f;f=HT[f].parent;

}

HC[i].code=new char[n-start];

strcpy_s(HC[i].code,n-start,&cd[start]);

}

delete cd;

}

int Locate(HuffmanCode HC,char ch)

{

for(int i=0;i<=MVNum;i++)

{

if(ch==HC[i].data)

return i;

}

return -1;

}

void Encoding(HuffmanCode HC)

{

char c;int i;

ifstream fin;fin.open("f:\\TEMPASD\\ToBeTran.txt",ios::in);

ofstream fout;fout.open("f:\\TEMPASD\\CodeFile.txt",ios::out);

if(!fin)

{

cerr<<"File could not be open!"<

abort();

}

while(fin.get(c))

{

if(c<'A'||c>'Z')

continue;

i=Locate(HC,c);

fout<<HC[i].code;

}

fin.close();

fout.close();

}

void Decoding(HuffTree HT)

{

char c;int i=2*MVNum-1;

ofstream fout("f:\\TEMPASD\\TextFile.txt",ios::out);

ifstream fin("f:\\TEMPASD\\CodeFile.txt",ios::in);

if(!fin)

{

cerr<<"File could not be open!"<

abort();

}

while(fin.get(c))

{

if(c=='0')

i=HT[i].lchild;

else

i=HT[i].rchlid;

if(HT[i].lchild==0&&HT[i].rchlid==0)

{

fout<<HT[i].data;

i=2*MVNum-1;

}

}

fout<<'\n';

fout.close();

fin.close();

}

void Print(HuffmanCode HC)

{

char c;int flag=1;

ifstream fin("f:\\TEMPASD\\CodeFile.txt",ios::in);

ofstream fout("f:\\TEMPASD\\CodePrin.txt",ios::out);

while(fin.get(c))

{

cout<

if(flag==50)

{

cout<

fout<<'\n';

flag=1;

}

}

 

}

void printhelp(HuffTree &HT,string ss,int num)

{

if(HT[num].lchild<=0&&HT[num].rchlid<=0)

{

ss+="   ";

cout<<ss<<HT[num].data<

return;

}

ss+="   ";

printhelp(HT,ss,HT[num].rchlid);

cout<<ss<<HT[num].data<

printhelp(HT,ss,HT[num].lchild);

}

void Tree_printing(HuffTree &HT)

{

if(HT[2*MVNum-1].lchild==0||HT[2*MVNum-1].rchlid==0)

Initialization_1(HT,MVNum);

string ss="";

printhelp(HT,ss,2*MVNum-1);

}

 

//源.cpp

#include"Huff.h"

int main()

{

HuffTree HT=new HTNode[2*MVNum];int flag=1;char ch;

HuffmanCode HC;

for(int i=0;i<=2*MVNum-1;i++)

{

HT[i].data='#';

HT[i].parent=0;

HT[i].lchild=0;

HT[i].rchlid=0;

}

while(1)

{

cout<<"-----------哈夫曼编/译码器-----------"<

cout<<"-----------I.初始化------------------"<

cout<<"-----------E.编码--------------------"<

cout<<"-----------D.译码--------------------"<

cout<<"-----------P.印代码文件--------------"<

cout<<"-----------T.印哈夫曼树--------------"<

cout<<"-----------Q.退出程序----------------"<

cin>>ch;

switch(ch)

{

case 'I':Initialization(HT,MVNum);break;

case 'E':CreateHuffmanCode(HT,HC,MVNum);Encoding(HC);break;

case 'D':Decoding(HT);break;

case 'P':Print(HC);break;

case 'T':Tree_printing(HT);break;

case 'Q':flag=0;break;

default:break;

}

if(flag==0)

break;

}

return 0;

}


你可能感兴趣的:(课程作业)