算法设计与分析课程设计报告.docx
《算法设计与分析课程设计报告.docx》由会员分享,可在线阅读,更多相关《算法设计与分析课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
![算法设计与分析课程设计报告.docx](https://file1.bdocx.com/fileroot1/2023-7/1/042c95dc-9a86-45d5-b46c-c7d2ddd4c67f/042c95dc-9a86-45d5-b46c-c7d2ddd4c67f1.gif)
算法设计与分析课程设计报告
压缩软件课程设计书
一、问题描述:
建立一个文本文件,统计该文件中各字符频率,对各字符进行Huffman编码,将该文件至翻译成Huffman编码文件,再将Huffman编码文件翻译成原文件。
二、算法分析及思路:
对于该问题,我们做如下分析:
(1)首先得构造出哈弗曼树,我们用函数HuffmanTree(intw[],ints[],intn)设计;
(2)在构建哈弗曼树的基础上,进一步实现哈弗曼编码问题,我们用函数Huffmancode(charwen[])设计;
(3)实现哈弗曼编码后再进一步实现哈弗曼译码问题,我们用函数Huffmandecode()设计;
(4)其中编码问题中,得进一步统计出各个字符在文件中的频率,并进行一些必要的标记,我们用函数runhuffman(charwen[])设计;
(5)在译码过程中,还有必要的一步是比较原文件与译码后的文件是否相同,我们用函数compare(charwen[])设计;
(6)其中的文件输入我们用到类”fstream.h”中的输入输出流,并在运行的文件夹中建立一个文件名为逍遥游的文本文件,且在逍遥游文件中输入需要编码的数据。
三、主要解决的设计问题:
1.写一个对txt文件压缩和解压的程序,使用动态编码。
2.使用Huffman编码压缩和解压时,Huffman树的存储可以直接存储树结构,也可以存储所有字符的频度或权值,然后读取时建立Huffman树;
3.使用Huffman编码压缩和解压时,注意定义压缩码的结束标记,可以使用一个特殊的字符作为结束标记,也可以在压缩码之前存储其比特长度;如果使用一个特殊字符作为结束标记,则其频度为1,需要在建立Huffman树时把它看作一个独立的字符进行建树。
4.使用Huffman编码压缩和解压时,在一个缓冲区里面收集压缩码比特流,每当收集的比特数满8时,可以把这8比特通过位操作合并成一个字节写入文件(当然也可以收集满一定数目的字节后再写入文件)。
写入文件的最小信息单位为字节。
四、程序设计的流程图:
五、输入和输出说明:
1、数据输入:
由文件input.txt提供输入需要压缩的内容;
2、结果输出:
将压缩好的文件内容输出到《编码后的文件.txt》中,再由《编码后的文件.txt》解压到《译码后的文件.txt》中。
六、程序及其注解:
1、数据结构设计(即类的设计,包括类的数据成员、函数成员)
类的设计用HuffmanTree.h保存如下:
#include
#include
usingnamespacestd;
constintMaxSize=512;
//--------------------------------------------------------------
structelement//哈夫曼树的结点
{
intstr;//记录字符在数组中的位置
intweight;//字符出现频率(权值)
intlchild,rchild,parent;//哈夫曼树各个指针变量
charbits[30];//存储哈夫曼编码的数组
};
//--------------------------------------------------------------
classHuffmanTree
{
elementhufftree[MaxSize];//存放哈夫曼树结点的数组
intnum;//结点数
public:
HuffmanTree(intw[],ints[],intn);
voidSelect(intn,int&s1,int&s2);
voidHuffmancode(charwen[]);//哈夫曼编码
voidHuffmandecode();//哈夫曼译码
};
//--------------------------------------------------------------
classRun
{
public:
voidhuffman(charwen[]);//将编码后的文件译成原文件
voidrunhuffman(charwen[]);//统计各字符频率
voidcompare(charwen[]);//比较逍遥游文件和译码后的文件
};
//--------------------------------------------------------------
2、算法设计(类的函数成员的具体设计)
(1)算法一设计用HuffmanTree.cpp保存如下:
#include
#include"HuffmanTree.h"
usingnamespacestd;
//-------------------------------------------------------------------
voidHuffmanTree:
:
Select(intn,int&s1,int&s2)
{
s1=-1;
s2=-1;
for(inti=0;i<=n;i++)
{
if(hufftree[i].parent==-1)
{
if(s1==-1){s1=i;continue;}
if(s2==-1){s2=i;continue;}
if(hufftree[i].weights1=i;
elseif(hufftree[i].weights2=i;
}
}
}
//-------------------------------------------------------------------
HuffmanTree:
:
HuffmanTree(intw[],ints[],intn)
{
num=n;
inti1,i2;
i1=i2=0;
for(inti=0;i<2*num-1;i++)//外部叶子结点数为num个时,内部结点数为n-1,整个哈夫曼树的需要的结点数为2*num-1.
{
hufftree[i].parent=-1;
hufftree[i].lchild=-1;
hufftree[i].rchild=-1;
}
for(intj=0;j{
hufftree[j].weight=w[j];
hufftree[j].str=s[j];
}
for(intk=num;k<2*num-1;k++)//构建哈夫曼树
{
Select(k-1,i1,i2);//在hufftree中找权值最小的两个结点i1和i2
hufftree[i1].parent=k;
hufftree[i2].parent=k;
hufftree[k].weight=hufftree[i1].weight+hufftree[i2].weight;
hufftree[k].lchild=i1;
hufftree[k].rchild=i2;
}
}
//-------------------------------------------------------------------
voidHuffmanTree:
:
Huffmancode(charwen[])
{
ifstreamin(wen);
ofstreamout("编码后的文件.txt");
intstart=MaxSize-1;
intcha=0;
charcd[MaxSize];//存放一个编码
cd[MaxSize-1]='\0';
for(inti=0;i{
start=MaxSize-1;
intc,f;
for(c=i,f=hufftree[i].parent;f!
=-1;c=f,f=hufftree[f].parent)
{
if(hufftree[f].lchild==c)//置左分支编码0
cd[--start]='0';
elsecd[--start]='1';//置右分支编码1
}
strcpy(hufftree[i].bits,&cd[start]);//将编码存放在相应结点存储哈夫曼编码的数组中
}
cout<<"字符在数组中的下标及其编码如下:
";//输出字符在数组中的位置及其编码
for(intk=0;k{
if(k%3==0)cout<cout<"<}
cout<for(charch;in.get(ch);)//将逍遥游文件中各个字符转变成相应的编码,写入编码后的文件中
{
if((int)ch<0)cha=(int)ch+256;
elsecha=(int)ch;
for(intj=0;jif(hufftree[j].str==cha)
out<}
cout<<"编码成功!
"<}
//-------------------------------------------------------------------
voidHuffmanTree:
:
Huffmandecode()
{
ifstreamin("编码后的文件.txt");
ofstreamout("译码后的文件.txt");
inti=2*num-2;
for(charb;in>>b;)
{
if(b=='0')i=hufftree[i].lchild;
elsei=hufftree[i].rchild;
if(hufftree[i].lchild==-1)
{
out<<(char)hufftree[i].str;
i=2*num-2;
}
}
cout<<"译码成功!
"<}
//-------------------------------------------------------------------
(2)算法二设计用HuffmanRun.cpp保存如下:
#include
#include"HuffmanTree.h"
usingnamespacestd;
//---------------------------------------------------------
voidRun:
:
runhuffman(charwen[])
{
ifstreamin(wen);
intw[MaxSize];
intweight[MaxSize];//存放各个字符的频率
intstr[MaxSize];//存放逍遥游文件中各个字符在数组w中的位置(下标)
inti=0;
intn=0;
intcha=0;
for(intj=0;jw[j]=0;
/*从文件逍遥游中依次读入字符,根据字符的ASCII码值将字符存入str[]数组的相应位置
而weight[]数组的相应位置则记录该字符出现的频率*/
for(charch;in.get(ch);)
{
if((int)ch<0)cha=(int)ch+256;//中文的ASCII码值为负数,加上256使其可以存放在数组中
elsecha=(int)ch;
w[cha]++;
}
for(intk=0;kif(w[k]!
=0)
{
str[n]=k;
weight[n]=w[k];
n++;
}
cout<<"字符在数组中的下标及其权值如下:
";//输出字符在数组中的位置及其权值
for(intp=0;p{
if(p%6==0)
cout<cout<"<}
cout<HuffmanTreeh(weight,str,n);//构造哈夫曼树
h.Huffmancode(wen);//利用哈夫曼树进行编码及译码
h.Huffmandecode();
}
//---------------------------------------------------------
voidRun:
:
huffman(charwen[])
{
ifstreamin(wen);
intweight[MaxSize];//存放各个字符的频率
intstr[MaxSize];//存放逍遥游文件中各个字符在数组w中的位置(下标)
intn=0;
HuffmanTreeh(weight,str,n);//构造哈夫曼树
h.Huffmandecode();
}
voidRun:
:
compare(charwen[])
{
ifstreamina(wen);
ifstreaminc("译码后的文件.txt");
charstringa[100000];
inti=0;
intflag=0;
charstringc[100000];
intj=0;
for(charcha;ina>>cha;)//将文件逍遥游的内容读入数组stringa[]
{
stringa[i]=cha;
i++;
}
stringa[i]='\0';
for(charchc;inc>>chc;)//将译码后的文件内容读入数组stringc[]
{
stringc[j]=chc;
j++;
}
stringc[j]='\0';
/*比较文件逍遥游和译码后的文件内容,若相同则说明编码正确,若不同,
则说明编码错误*/
for(intk=0;stringa[k]!
='\0'&&stringc[k]!
='\0';k++)
if(stringa[k]!
=stringc[k])flag=0;
if(stringa[k]=='\0'&&stringc[k]=='\0')flag=1;
elseflag=0;
if(flag==0)
cout<<"逍遥游文件与译码后的文件不相同,编码错误!
"<else
cout<<"逍遥游文件与译码后的文件相同,编码正确!
"<}
//---------------------------------------------------------
(3)实现算法设计的主程序用HaffmanMain.cpp保存如下:
#include
#include"HuffmanTree.h"
usingnamespacestd;
voidmain()
{
charwenjian[20];intt=1;
while
(1)
{
if(t==1)
{cout<<"请输入要编码的文件名:
";
cin>>wenjian;
Runmanager;
manager.runhuffman(wenjian);
pare(wenjian);}
else
{cout<<"请输入要译码的文件名:
";
cin>>wenjian;
Runmanager;
manager.huffman(wenjian);}
cout<<"请继续选择需要执行的功能:
"<cout<<"请问您是需要编码文件还是译码文件?
"<cout<<"如果是要编码文件,那么请输入1;"<cout<<"如果是要译码文件,那么请输入0。
"<cin>>t;
}
}
七、程序运行结果及分析:
该课程设计实现了哈弗曼编码及译码问题,其中有一些独到之处,同时也有很多不足之处。
比如说:
其中的由编码文件直接翻译成译码文件没有单独实现,也没有很好的算法直接描述,而正好该问题在实际用途中很广泛,一般都要由一些特定规则单独实现译码问题。
希望在以后的进一步学习中能很好的掌握该问题的算法优化。