课程设计报告
课程名称:操作系统 实验题目:文件压缩程序
院 系:计算机科学与工程学院 班 级:
姓 名: 学 号:
二○一一年七月一日
一、 需求分析:
有两种形式的重复存在于计算机数据中,文件压缩程序就是对这两种重复进行了压
缩。
一种是短语形式的重复,即三个字节以上的重复,对于这种重复,压缩程序用两个数字:1.重复位置距当前压缩位置的距离;2.重复的长度,来表示这个重复,假设这两个数字各占一个字节,于是数据便得到了压缩。
第二种重复为单字节的重复,一个字节只有256种可能的取值,所以这种重复是必然的。给 256 种字节取值重新编码,使出现较多的字节使用较短的编码,出现较少的字节使用较长的编码,这样一来,变短的字节相对于变长的字节更多,文件的总长度就会减少,并且,字节使用比例越不均匀,压缩比例就越大。
编码式压缩必须在短语式压缩之后进行,因为编码式压缩后,原先八位二进制值的字节就被破坏了,这样文件中短语式重复的倾向也会被破坏(除非先进行解码)。另外,短语式压缩后的结果:那些剩下的未被匹配的单、双字节和得到匹配的距离、长度值仍然具有取值分布不均匀性,因此,两种压缩方式的顺序不能变。
本程序设计只做了编码式压缩,采用Huffman编码进行压缩和解压缩。Huffman编码是一种可变长编码方式,是二叉树的一种特殊转化形式。编码的原理是:将使用次数多的代码转换成长度较短的代码,而使用次数少的可以使用较长的编码,并且保持编码的唯一可解性。根据 ascii 码文件中各 ascii 字符出现的频率情况创建 Huffman 树,再将各字符对应的哈夫曼编码写入文件中。同时,亦可根据对应的哈夫曼树,将哈夫曼编码文件解压成字符文件.
二、 概要设计:
主程序流程图:
主函数 测试 统计字符,得出统计出的字符的权值n 退出 扫描压缩文件,载入字符信息 输入测试字符串 根据权值进行建立Huffman树 统计字符信息,建立Huffman曼树 输出Huffman树 根据权值进行建立Huffman树 输出Huffman树 编码 根据Huffman树,求得对应字符的Huffman编码 解码 输入Huffman编码,求得解码 输出编码 压缩编码 解压 生成压缩文件 生成新的文本文档
压缩过程的实现:
压缩过程的流程是清晰而简单的: 1. 创建 Huffman 树 2. 打开需压缩文件
3. 将需压缩文件中的每个 ascii 码对应的 huffman 编码按 bit 单位输出生成压缩文件压缩结束。
其中,步骤 1和步骤 3是压缩过程的关键。
步骤1:这里所要做工作是得到 Huffman数中各叶子结点字符出现的频率并进行创建.统计字符出现的频率可以有很多方法:如每次创建前扫描被创建的文件,“实时”的生成各字符的出现频率;或者是创建前即做好统计.这里采用的是前一种方法。
步骤 3: 将需压缩文件中的每个 ascii 码对应的 huffman 编码按 bit 单位输出. 这是本压缩程序中最关键的部分: 这里涉及“转换”和“输出”两个关键步骤: “转换”部分大可不必去通过遍历 Huffman 树来找到每个字符对应的哈夫曼编码,可以将每个 Huffman 码值及其对应的 ascii 码存放于如下所示的结 构体中:
解压缩过程的实现:
如果说,压缩的过程可以通过查找 codeList 来加速实现的话,而解压缩则必须通过查找 huffman 树才能加以实现.查找的过程是简单的,可以根据
huffman 树的性质来做,当 haffCode的当前 bit 位为 0 时,则向左枝展开搜索;当前bit 位为1时,则向右枝展开搜索,当遇到叶子结点时,则输出haffCode对应的 asciiCode。
三、 详细设计:
核心算法源程序:
Huffman树建立源程序:
//------------------------------------------------------------- //huffmantree.h //霍夫曼树
#ifndef HUFFMANTREE #define HUFFMANTREE
#define Defaultsize 300
#include class Code { public: int code; Code *link; Code(int c=0,Code *l=NULL):code(c),link(l){}; }; class CharNameNode { public: unsigned char charname; //要这样才行 Code *link; CharNameNode(unsigned char c=0,Code *l=NULL):charname(c),link(l){}; }; template class HuffmanTree:public BinaryTree { public: int key; HuffmanTree(){}; HuffmanTree(HuffmanTree Type temp=0; //可能有变 key=ht1.key+ht2.key; root= new BinTreeNode void Build(int *fr,Type *value,int n,HuffmanTree template void HuffmanTree HuffmanTree HuffmanTree hp=MinHeap< HuffmanTree HuffmanTree hp.RemoveMin(newtree); } template if(start==NULL) return; // if(start->GetData()!=0) //是叶结点 严重错误,可能叶结点也是0!! if(start->GetLeft()==NULL&&start->GetRight()==NULL) { Node[i].charname=start->GetData(); Node[i].link=NULL; if(first==NULL) return; Node[i].link=new Code(first->code); Code *p=first->link,*q=Node[i].link; while(p!=NULL) { q->link=new Code(p->code); q=q->link; p=p->link; } q->link=NULL; i++; return; } Code *temp=new Code; //进入左子树 assert(temp); if(first==NULL) first=last=temp; else { last->link=temp; last=last->link; } Path(start->GetLeft(),first,last,Node,i); last->code=1; Path(start->GetRight(),first,last,Node,i); temp=first; if(first==last) { delete last; first=last=NULL; return; } while(temp->link!=last) temp=temp->link; temp->link=NULL; delete last; last=temp; } #endif 实现二叉树的算法源程序: //--------------------------------------------------------------------- //bintree.h //用指针实现的二叉树 //Type 类型必须有重载<<与>>及=运算 #ifndef BINTREE #define BINTREE #include int Max(int a,int b) { return a>b?a:b; } template template friend class BinaryTree BinTreeNode():leftchild(NULL),rightchild(NULL){}; BinTreeNode(Type item,BinTreeNode BinTreeNode void SetLeft(BinTreeNode BinTreeNode template BinaryTree():root(NULL){}; BinaryTree(const BinaryTree virtual int IsEmpty(){ return root==NULL?1:0; } virtual BinTreeNode return root==NULL||root==current? NULL : Parent(root,current); } virtual BinTreeNode return root!=NULL? current->leftchild : NULL; } virtual BinTreeNode return root!=NULL? current->rightchild : NULL; } virtual int Insert(const Type &item); virtual int Find(const Type &item)const; BinTreeNode friend int Equal(BinTreeNode friend int operator ==(const BinaryTree void InOrder(); //遍历 void PreOrder(); void PostOrder(); //****************************************** //一些应用 int Size(){ return Size(root);} //统计结点数 int Depth(){ return Depth(root);} //计算树的深度 int Leaves(){ return Leaves(root);} int Degrees1(){ return Degrees1(root);} int Degrees2(){ return Degrees2(root);} protected: BinTreeNode BinTreeNode //****************************************** void InOrder(BinTreeNode //****************************************** //一些应用 int Size(const BinTreeNode template BinTreeNode if(orignode==NULL) return NULL; BinTreeNode temp->leftchild=Copy(orignode->leftchild); temp->rightchild=Copy(orignode->rightchild); return temp; } template BinaryTree root=new BinTreeNode template void BinaryTree Destroy(); // Destroy(root);root=NULL; //为什么要这样??? root=Copy(bt1.root); } template void BinaryTree if(current!=NULL) { Destroy(current->leftchild); &bt1,const Destroy(current->rightchild); delete current; } } template BinTreeNode if(start==NULL) return NULL; if(start->leftchild==current || start->rightchild==current) return start; BinTreeNode if((p=Parent(start->leftchild, current))!=NULL) //在start的左子树中找 return p; else return Parent(start->rightchild,current); } template int BinaryTree if(current==NULL) return 0; BinTreeNode else if(current->rightchild==NULL) current->rightchild=p; else Insert(current->leftchild,item); //这样插可是构不成树状的!估且一用吧 return 1; } template int BinaryTree if(root==NULL) { root=new BinTreeNode return Insert(root,item); } template int BinaryTree if(current==NULL) return 0; if(current->data==item) return 1; int k; if((k=Find(current->leftchild,item))!=0) return 1; else return Find(current->rightchild,item); } template int BinaryTree return Find(root,item); } template int Equal(BinTreeNode if(a==NULL&&b==NULL) return 1; if(a!=NULL&&b!=NULL&&a->GetData()==b->GetData() &&Equal(a->GetLeft(),b->GetLeft())&&Equal(a->GetRight(),b->GetRight())) return 1; return 0; } template int operator ==(const BinaryTree return Equal(bt1.root,bt2.root); } template istream& operator>>(istream &in,BinaryTree Type item; cout<<\"构造二叉树:\\n\"; cout<<\"输入数据(用\"< Tree.Insert(item); cout<<\"输入数据(用\"< return in; } template ostream& operator<<(ostream &out,BinaryTree out<<\"二叉树的前序遍历.\\n\"; Tree.PreOrder(); out< template void BinaryTree InOrder(root); } template { if(current!=NULL) { InOrder(current->leftchild); cout << current->data<<' '; InOrder(current->rightchild); } } template void BinaryTree PreOrder(root); } template void BinaryTree if(current!=NULL) { cout< template void BinaryTree PostOrder(root); } template void BinaryTree if(current!=NULL) { PostOrder(current->leftchild); PostOrder(current->rightchild); cout< //*************************************************** //一些应用 template int BinaryTree if(t==NULL) return 0; else return 1+Size(t->leftchild)+Size(t->rightchild); } template int BinaryTree if(t==NULL) return -1; else return 1+Max(Depth(t->leftchild),Depth(t->rightchild)); } template int BinaryTree if(t==NULL) return 0; if(t->leftchild==NULL&&t->rightchild==NULL) //t是叶子结点 return 1; return Leaves(t->leftchild)+Leaves(t->rightchild); } template int BinaryTree if(t==NULL) return 0; if((t->leftchild==NULL&&t->rightchild!=NULL) ||(t->leftchild!=NULL&&t->rightchild==NULL)) //t的度为1 return 1+Degrees1(t->leftchild)+Degrees1(t->rightchild); return Degrees1(t->leftchild)+Degrees1(t->rightchild); } template int BinaryTree if(t==NULL) return 0; if(t->leftchild!=NULL&&t->rightchild!=NULL) //t 的度为2 return 1+Degrees2(t->leftchild)+Degrees2(t->rightchild); return Degrees2(t->leftchild)+Degrees2(t->rightchild); } #endif 堆程序: //--------------------------------------------------------- //堆 #include //Type 类型必须有key成员!及<< >> =及拷贝构造运算! template public: virtual int Insert(const Type &)=0; virtual int RemoveMin(Type &)=0; }; template class MinHeap:public MinPQ