algorithm-in-python/project/huffman/huffman.tex
2018-07-11 19:26:24 +08:00

310 lines
11 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%\document{article}
\documentclass[UTF8]{ctexart}
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage{float}
\usepackage{listings}
\title{Huffman编码压缩}
\author{朱河勤 PB16030899}
\pagestyle{fancy}
\lfoot{朱河勤 PB16030899}
\chead{Huffman编码压缩}
\rfoot{2017/11/11}
\begin{document}
\maketitle
\tableofcontents
\section{需求分析}
\paragraph{1}
正确创建huffman 树并得到huffman编码
\paragraph{2}
压缩编码文件,使一般的文本文件变小,二进制文件可能不会变小
\paragraph{3}
解压文件,注意生成的文件要考虑同名,所以要考虑文件名的操作
\paragraph{4}
压缩解压时显示进度条
\paragraph{5}
解压完毕,统计文件数,压缩率,压缩时间等等
\section{概要设计}
\subsection{结点node}
ADT linkList\{\\
\paragraph{数据对象}key , val, visited ,left,right \\
\paragraph{数据关系}:属性集合\\
\paragraph{基本操作}
\subparagraph{node()} 新建一个结点
\subparagraph{node( const node\& nd} 复制一个结点
\subparagraph{operator<}重载操作符<
\}
\subsection{huffman树}
ADT linkList\{\\
\paragraph{数据对象}root , encode\_map, total\\
\paragraph{数据关系}:属性集合\\
\paragraph{基本操作}
\subparagraph{huffman( map)}传递字符的频率信息以map形式 然后建立huffman树
\subparagraph{encode(string)} 传递文件名,压缩
\subparagraph{decode(string)} 传递文件名,解压缩
\subparagraph{preorder()}先序遍历获得huffman编码
\subparagraph{display}显示所有信息包括结点信息以及huffman编码
\}
\section{详细设计}
\subsection{编码,解码算法}
\begin{lstlisting}[language=c++]
template<typename ky,typename wt>
void huffman<ky,wt>::preOrder(node<ky, wt>* nd,string s)
{
if(nd->left == NULL){
encode_map[nd->key] =s;
decode_map[s] = nd->key;
delete nd;
return ;
}
preOrder(nd->left,s+'0');
preOrder(nd->right,s+'1');
delete nd;
}
template<typename ky,typename wt>
string huffman<ky,wt>::decode(string zipfile_name)
{
string uniFileName(string);
FILE * src = fopen(zipfile_name.c_str(),"rb");
char file_name[nameLength];
fgets(file_name,nameLength,src);
int ct=-1;
while(file_name[++ct]!='\n');
int pos = zipfile_name.find('.');
if(pos==string::npos)pos=zipfile_name.size();
string name(zipfile_name.substr(0,pos)) ,suffix(file_name,file_name+ct),file(name+suffix);
file=uniFileName(file);
cout<<"extracting compressed file :"<<file<<endl;
FILE * f = fopen(file.c_str(),"wb");
if(!f){
cerr<<"Error! Maybe the file doesn't exist!"<<endl;cerr<<"open error!"<<endl;
abort( );
}
char t[numDigit];
fgets(t,numDigit,src);
int sz=atoi(t);
char code[sz];
fread(code,sz,1,src);
cout<<code<<endl;
cout<<"SZ"<<sz<<endl;
// return string();
map<string,char> mp;
int idx=0;
for(int i =0;i<sz;++i ){
if(code[i]==' '){
mp[string(code+idx,code+i)]=code[++i];
idx=i+1;
}
}
mapprint(mp);
char buff[once],*p;
string res;
while(!feof(src)){
p=buff;
int cur=0;
while(cur<once){
ToEightBin(p,fgetc(src));
}
cout<<buff;
return string();
while(buff[++cur]!='\0');
for(int i =0;i<cur;++i){
res.append(1,buff[i]);
if(mp.count(res)!=0){
fputc(mp[res],f);
res.clear();
}
}
}
fclose(src);
fclose(f);
}
template<typename ky,typename wt>
string huffman<ky,wt>::encode(string file_name)
{
string uniFileName(string);
int pos =file_name.rfind('.');
if(pos==string::npos)pos=file_name.size();
string zipfile = file_name.substr(0,pos)+string(".zzip");
zipfile = uniFileName(zipfile);
cout<<"generating zip file :"<<zipfile<<endl;
FILE * dst = fopen(zipfile.c_str(),"wb");
FILE * f = fopen(file_name.c_str(),"rb");
fputs(file_name.substr(pos).c_str(),dst);
fputc('\n',dst);
string data;
for(class map<string,ky>::iterator i=decode_map.begin();i!=decode_map.end() ;++i ){
data.append((i->first));
data.append(" ");
data+=(i->second);
}
cout<<data<<endl<<"SZ"<<data.size()<<endl;;
// mapprint( encode_map);
// return string();
int data_size = data.size(); // calculate the size of the code_data
char sz[numDigit];
itoa(data_size,sz,numDigit);
int ct=0;
for(;sz[ct];++ct)fputc(sz[ct],dst);
fputc('\n',dst);
// cout<<data<<data_size<<endl;
fwrite(data.c_str(),data_size,1,dst);
int sum=0,digit=0,num;
char src[once];
while(!feof(f)){
num = fread(src,sizeof(char),once,f);
string tmp;
for(int i =0;i<num;++i){
tmp=encode_map[src[i]];
for(int j =0;j<tmp.size();++j){
if(tmp[j])sum += 1<<(digit%8);
++digit;
if(digit==8){
fputc(sum,dst);
digit=sum=0;
}
}
}
}
if(digit!=0){ //mark
fputc(sum,dst);
fputc(digit,dst);
}
else fputc(0,dst);
fclose(f);
fclose(dst);
return zipfile;
}
\end{lstlisting}
\subsection{输出进度条}通过输出@以显示当天进度,提示用户
\subsection{改变文件名}由于当前工作目录可能有解压或压缩后的同名文件,要进行处理,我的方法是在后缀前,文件名后加上(n) 其中n为数字
\subsection{统计信息}处理后,统计信息,包括压缩的文件名目录,所用的时间,文件大小,压缩率等等
\section{调试分析}
\subsection{编码信息的存储}
我先计算了编码信息的大小,然后存在文件中,以键值对的形式,如''001 k''再存储编码信息,这样就能更快的读取,并能节省空间
\subsection{最后一个字节}
由于储存时一char八位一次地储存所以最后一字节可能凑不齐我通过补0地方式并在最后再增加一字节记录补0的个数来解决
\subsection{文件名的处理}
文件名要要记录后缀以识别文件种类以及文件是否存在能否打开生成的文件是否重名。比如当发现重名时你要生成n形式但可能(n)也已经存在所以要一直检查12...检查到一个较大的数或者是第一次未出现时才能确定N
\section{用户手册}
本程序需要在windows环境下运行可以直接打开.exe文件或者在命令行支持命令行参数\
下面为程序运行界面
\begin{verbatim}
C:\Users\mbinary\Desktop\dataStructrue\huffman
input file names separated by space
OR press enter to use the default file:初心未改.mp4
opening 初心未改.mp4...
the file 初心未改.zzip already exists! continue? [Y/n]:generating zip file :初心未改(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
compress 初心未改.mp4 successfully
continue to uncompress? [Y/n]
the file 初心未改(2).mp4 already exists! continue? [Y/n]:
extracting compressed file :初心未改(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
get 初心未改(3).mp4 successfully
dealt file number 1
初心未改.mp4 18891ms 8274.84KB/8296.13KB :99.74%
\end{verbatim}
\section{测试结果}
\subsection{文本文件}
输入了几个不存在的文件,检查强壮性。同时发现文本文件压缩率还是很令人满意的
\begin{verbatim}
input file names separated by space
OR press enter to use the default file:初心未改.mp4
em cvem ven em.cc
opening em...
Path Error! Opening em Failed
opening cvem...
Path Error! Opening cvem Failed
opening ven...
Path Error! Opening ven Failed
opening em.cc...
the file em.zzip already exists! continue? [Y/n]:
generating zip file :em(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
compress em.cc successfully
continue to uncompress? [Y/n]
the file em(2).cc already exists! continue? [Y/n]:
extracting compressed file :em(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
get em(3).cc successfully
dealt file number 4
em.cc 2266ms 4.69KB/7.57KB :61.87%
\end{verbatim}
\subsection{二进制文件1}
几乎没有压缩,原因应该是.exe文件本来就压缩得很好了几乎已经是随机的编码了所以huffman没有效果这也是文件不能重复压缩直至没有大小的原因。
\begin{verbatim}
input file names separated by space
OR press enter to use the default file:初心未改.mp4
GitHubDesktopSetup.exe
opening GitHubDesktopSetup.exe...
the file GitHubDesktopSetup.zzip already exists! continue? [Y/n]:
generating zip file :GitHubDesktopSetup(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
compress GitHubDesktopSetup.exe successfully
continue to uncompress? [Y/n]
the file GitHubDesktopSetup(2).exe already exists! continue? [Y/n]:
extracting compressed file :GitHubDesktopSetup(2).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
get GitHubDesktopSetup(3).exe successfully
dealt file number 1
GitHubDesktopSetup.exe 309610ms 81718.46KB/81718.46KB :100.00%
\end{verbatim}
\subsection{二进制文件2}
\begin{verbatim}
input file names separated by space
OR press enter to use the default file:初心未改.mp4
opening 初心未改.mp4...
the file 初心未改.zzip already exists! continue? [Y/n]:generating zip file :初心未改(3).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
compress 初心未改.mp4 successfully
continue to uncompress? [Y/n]
the file 初心未改(3).mp4 already exists! continue? [Y/n]:
extracting compressed file :初心未改(3).zzip
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
get 初心未改(4).mp4 successfully
dealt file number 1
初心未改.mp4 13688ms 8274.84KB/8296.13KB :99.74%
\end{verbatim}
\clearpage
\end{document}