哈夫曼编码译码实训报告

哈夫曼编码译码实训报告
哈夫曼编码译码实训报告

实训报告

题目:哈夫曼编码和译码

院系:信息科技学院

专业:计算机科学与技术

姓名:吴平

学号: 1451200205

指导教师:邱勋拥

日期:2016年6月29日

桂林电子科技大学信息科技学院

目录

一、设计目的 (4)

二、设计内容 (4)

三、概要设计 (4)

四、详细设计 (6)

4.1、头文件的定义: (6)

4.2、模块接口设计: (6)

4.3、主函数MAIN(): (6)

4.4、主菜单界面: (7)

4.5、功能的执行过程: (7)

4.6、定义哈夫曼树类: (10)

4.7、哈夫曼树的建立: (11)

4.8、哈弗曼编码: (12)

4.9、哈夫曼译码: (12)

五、测试与调试 (13)

5.1、概述 (13)

5.2、程序测试 (13)

六、系统维护 (15)

七、归纳总结 (15)

八、附源程序代码 (16)

哈夫曼编码译码

一、设计目的

通过对哈夫曼编码译码系统的设计编写原代码,深刻掌握C++语言中各个语法以及数据结构与C++的联系与结合,其中还应用了C语言的结构体的知识。函数的应用,使我们对结构体,链表,文件以及程序的操作更加熟悉。初步掌握中,大型程序设计中的各个步骤,流程,以及开发过程中遇到问题的处理方法,为以后的学习打下基础。并且通过课程设计,将上学期所学的C++程序设计以及这学期所学的数据结构的知识联系结合,培养自己的动手能力,加强相关学科之间的联系。

二、设计内容

本系统以哈夫曼编码译码为主要背景,设计和实现了一个小型哈夫曼编码译码器系统。主要有以下功能:

1.系统以Dos界面显示来运行工作,界面清晰直观,便于用户操作。

2.哈夫曼树的创建,包括双亲,左孩子、右孩子和权值。

3.创建哈夫曼编码,输入一段字符和对应字符的权值并以.txt的形式保存在文件中。

4.哈夫曼译码,对之前创建的编码进行译码。

程序运行效果图如下图所示:

三、概要设计

采用模块化的程序设计方法,即将较大的任务按照一定的原则分为一个个较小的任务,然后分别设计各个小任务。需要注意的是划分出来的模块应该相对独立但又相关,

且容易理解。可以用模块化层次结构图(即模块图)来分析其任务的划分,一般从上到下进行,最上面一层是主模块,下面各层是其上一层模块的逐步细化描述。

本哈夫曼编码译码要求用c++语言编写实现,如图2.1所示,它由如下四大模块构成:○1.创建哈夫曼树:创建一个新的哈夫曼树,完成将字符初始化的操作。然后编码译码就可以读出相应的字符并进行编码译码。

②.创建哈弗曼编码:在新建的哈夫曼树的基础下,对字符进行编码并保存到文件。

③.进行哈夫曼译码:对之前已经进行好编码的字符进行译码。

④.退出程序。

四、详细设计

4.1、头文件的定义:

#include //程序中要用到文件流类ofstream,ofstream是在这个中定义的

#include

#include

#include //系统自带的字符串库函数,strcpy包含在这个头文件中4.2、模块接口设计:

class LinkList 定义一个链表类

class HuffmanTree 定义一个哈夫曼树

void HuffmanTree::CreatHuffmanTree(char ch[], int w[], int n)创建哈夫曼树string HuffmanTree::Encode(char ch)哈弗曼编码

LinkList HuffmanTree::Decode(string strCode)哈夫曼译码

4.3、主函数main():

main()函数主要实现了对整个程序的运行控制,以及相关功能模块的调用。

int main()

{

char *ch;

int *w,n=0;

int *p=&n;

ch=new char[100];

w=new int[100];

int x;

do

{

switch(x=actmenu())

{

case 1:f1(ch,w,p);break;

case 2:f2(ch,w,n);break;

case 3:f3(ch,w,n);break;

case 4:f4(ch,w,n);break;

}

}while(x);

cout<

return 0;

}

4.4、主菜单界面:

用户进入哈夫曼编码译码系统时,需要显示主菜单,提示用户进行选择,完成相应任务。此代码被main()函数调用。

int actmenu() //主菜单

{

system("cls"); //清屏函数

int k=0;

cout<<"\n\n\n\n\n\n\t哈夫曼编码译码系统";

cout<<"\n\n********************* 主菜单 *******************"<

cout<<"\n\n*********** 0.退出 ***********"<

cout<<"\n\n *********** 1.建树 *************"<

cout<<"\n\n ********** 2.编码 *************"<

cout<<"\n\n ************* 3.译码*************"<

cout<<"\n*****************请选择系统功能(0-3):"<

cin>>k;

return k;

}

4.5、功能的执行过程:

用户进入系统时,对每个功能进行操作,需要按这些条件输入,才能得到相应的正确的结果。

//每个功能的执行过程

void f1(char ch[],int w[],int *p)

{

char *ch1;

int *w1,n1,i;

cout<<"输入字符集中字符的个数:"<

cin>>n1;

*p=n1;

ch1=new char[n1];

w1=new int[n1];

cout<<"输入字符集中的字符:"<

for(i=0;i

cin>>ch1[i];

strcpy(ch,ch1); //将ch1复制给ch

strcpy(ch+sizeof(char)*n1,"\0"); //将括号里的内容复制给ch

cout<<"输入字符集中的字符的权值:"<

for(i=0;i

cin>>w1[i];

HuffmanTree hmTree(ch1,w1,n1);

system("PAUSE");

}

void f2(char ch[],int w[],int n)

{

HuffmanTree hmTree(ch,w,n);

string strText,strCode;

cout<<"请输入要编码的字符串:\n";

cin>>strText;

cout<<"文本串"<

ofstream ofile1("texrfile.txt"); //定义文件流对象,打开磁盘文件“texrfile.txt”

if(!ofile1) //如果打开失败,ofile1返回0值

{

cout<<"cannot open texrfile.txt\n";

return;

}

ofile1<

if(!ofile2) //如果打开失败,ofile2返回0值

{

cout<<"cannot open codefile.txt\n";

return;

}

for(int pos=0;pos

{

string strTmp=hmTree.Encode(strText[pos]);

cout<

ofile2<

}

cout<

system("PAUSE");

}

void f3(char ch[],int w[],int n)

{

HuffmanTree hmTree(ch,w,n);

string strText,strCode;

cout<<"读入codefile.txt,译码中...\n";

ifstream ifile("codefile.txt"); //定义输入文件流对象,以输入方式打开磁盘文件codefile.txt

if(!ifile)

{

cout<<"cannot open codefile.txt\n";

return;

}

ifile>>strCode; //从磁盘文件读入编码串

cout<<"编码串"<

LinkList lkText=hmTree.Decode(strCode);

lkText.Traverse();

lkText.Traversetofile();

cout<

system("PAUSE");

}

void f4(char ch[],int w[],int n)

{

HuffmanTree hmTree(ch,w,n);

string strText,strCode,reSult;

ifstream ifile1("codefile.txt");

if(!ifile1)

{

cout<<"cannot open codefile.txt\n";

return;

}

ifile1>>strCode;

ifstream ifile2("textfile.txt"); //定义输入文件流对象,以输入方式打开磁盘文件textfile.txt

if(!ifile2)

{

cout<<"cannot open textfile.txt\n";

return;

}

ifile2>>strText;

ifstream ifile3("result.txt"); //定义输入文件流对象,以输入方式打开磁盘文件result.txt

if(!ifile3)

{

cout<<"cannot open result.txt\n";

return;

}

ifile3>>reSult;

cout<<"textfile.txt文件内容:"<

<

system("PAUSE");

}

4.6、定义哈夫曼树类:

在创建哈夫曼树之前先要对哈夫曼树进行一个类的定义,并确定哈夫曼树的数据成员与成员函数,比如权值,双亲结点,左右孩子节点还有字符个数等。还有编码和译码的成员函数。

class HuffmanTree

{

protected:

HuffmanTreeNode *nodes; // 存储结点信息,nodes[0]未用

char *LeafChars; // 叶结点字符信息,LeafChars[0]未用

string *LeafCharCodes; // 叶结点字符编码信息,LeafCharCodes[0]未用

int curPos; // 译码时从根结点到叶结点路径的当前结点

int num; // 叶结点个数

// 辅助函数:

void Select(int cur,int &r1,int &r2); // nodes[1 ~ cur]中选择双亲为0,权值最小的叶结点r1,r2

void CreatHuffmanTree(char ch[],int w[],int n);

public:

HuffmanTree(char ch[], int w[], int n); // 由字符,权值和字符个数构造哈夫曼树

virtual ~HuffmanTree(); // 析构函数

string Encode(char ch); // 编码

LinkList Decode(string strCode); // 译码

};

void HuffmanTree::Select(int cur, int &r1, int &r2)

{

r1=r2=0; // 0表示空结点

for (int pos=1;pos<=cur;pos++)

{

if (nodes[pos].parent!=0) continue; // 只处理双亲为0的结点

if (r1==0)

{

r1=pos;

}

else

if(r2==0)

{

r2=pos;

}

else

if(nodes[pos].weight < nodes[r1].weight)

{

r1=pos;

}

else

if(nodes[pos].weight < nodes[r2].weight)

{

r2=pos;

}

}

}

4.7、哈夫曼树的建立:

在哈夫曼编码译码系统中,首先需要建立一个哈夫曼树,然后方便对相应字符串的编码与译码。

void HuffmanTree::CreatHuffmanTree(char ch[], int w[], int n) //创建哈弗曼树{

num=n; // 叶结点个数

int m=2*n-1; // 总结点个数

nodes = new HuffmanTreeNode[m+1]; // nodes[0]未用

LeafChars=new char[n+1]; // LeafChars[0]未用

LeafCharCodes=new string[n+1]; // LeafCharCodes[0]未用

int pos; // 临时变量

for (pos=1;pos<=n;pos++)

{ // 存储叶结点信息

nodes[pos].weight=w[pos-1]; // 权值

LeafChars[pos]=ch[pos-1]; // 字符

}

for (pos=n+1;pos<=m;pos++)

{ // 建立哈夫曼树

int r1, r2;

Select(pos-1,r1,r2);

nodes[r1].parent=nodes[r2].parent=pos; // r1,r2双亲为pos

nodes[pos].leftChild=r1; // r1为pos的左孩子

nodes[pos].rightChild=r2; // r2为pos的右孩子

nodes[pos].weight=nodes[r1].weight+nodes[r2].weight;//pos的权为r1,r2的权值之和

}

for (pos = 1; pos <= n; pos++)

{ // 求n个叶结点字符的编码

LinkList charCode; // 暂存叶结点字符编码信息

for (unsigned int child=pos,parent=nodes[child].parent;parent!=0;child=parent,parent=nodes[child ].parent)

{

if (nodes[parent].leftChild==child)

charCode.Insert(1,'0');

else

charCode.Insert(1,'1');

}

for(int i=1;i<=charCode.Length();i++)

LeafCharCodes[pos].append(1,charCode.GetElem(i));//没有直接可以从链表为字符串赋值的函数,只能一个字符一个字符的追加过去

}

curPos=m;

}

4.8、哈弗曼编码:

创建好哈夫曼树之后,就可以对相应的字符串进行编码了,根数创建好的哈夫曼树,我们输入我们所需要编码的字符,然后系统就会帮我们自动编码。

string HuffmanTree::Encode(char ch) //编码

{

for (int pos=1;pos<=num; pos++)

{

if (LeafChars[pos]==ch)

return LeafCharCodes[pos];// 找到字符,得到编码

}

return 0;

}

4.9、哈夫曼译码:

对编码后的0,1串进行译码得到相应的正确的字符编码。

LinkList HuffmanTree::Decode(string strCode)// 操作结果:对编码串strCode进行译码,返回编码前的字符序列

{

LinkList charList; // 编码前的字符序列

for (int pos = 0; pos < strCode.length(); pos++)// 处理每位编码

{

if (strCode[pos] == '0')

curPos=nodes[curPos].leftChild; // '0'表示左分支

else

curPos=nodes[curPos].rightChild; // '1'表示右分支

if (nodes[curPos].leftChild==0&&nodes[curPos].rightChild==0)// 译码时从根结点到叶结点路径的当前结点为叶结点

{

charList.Insert(charList.Length()+1,LeafChars[curPos]);

curPos =2*num-1;

}

}

return charList;

}

五、测试与调试

5.1、概述

一般情况下,为解决一个问题所编写的程序代码较长,可能包括几百条甚至成千上万条语句。在检查并排除所有语法错误后,还会有不易发现的逻辑错误,因此要对程序进行认真仔细的测试与调试。

测试是通过运行程序发现错误的过程,常见的错误有数据溢出、数组越界、进入死循环、语句顺序颠倒、多加“;”或少加“{}”等等。调试则是确定测试中找到的错误性质并改正错误的过程。测试与调试通常交替进行,即测试——调试——再测试——再调试。

能检查出尚未发现的、各种不同类型错误的测试才是成功的测试。测试程序需要测试用例,测试用例可用如下公式表示:测试用例=测试数据+预期结果。

好的测试用例应该是用尽可能少的测试数据发现尽可能多的错误,即发现错误的概率要大。要选择合适的测试数据,使系统在运行时尽量能执行到每条语句,以测试各指令是否正确。还应分别测试输入合法数据与非法数据时,程序的运行情况,。对于合法数据,还要考虑数据的一般性与特殊性,如求最大值的问题,应测试最大值在最前面、最后面、中间某一位置的情况。

测试程序时,用监视窗口可以随时查看变量或表达式的值,有时还可以将部分程序代码用注释符暂时括起来,缩短程序,以便压缩出错代码的范围

5.2、程序测试

在主菜单中选择1

当用户输入1并按回车键后,即可进入数据输入界面。若是第一次运行该程序,应能实现从键盘输入哈夫曼树信息到链表中,当输入完信息后,结束建树过程,返回主菜单界面。若非第一次运行该程序,应能实现从文件中读入编码信息到链表中,。其输入记录如图所示:

●在主菜单中选择2

当用户输入2并按回车键后,即可进入编码界面。其编码过程如图所示:

●在主菜单中选择3

当用户输入3并按回车键后,即可进入译码界面。其译码过程如图所示:

●在主菜单中选择0

当用户输入0并按回车键后,即可执行退出哈夫曼编码译码程序的操作,返回操作系统。其操作结果提示信息如图所示:

●在文件中的存储的字符串和编码如下:

六、系统维护

经测试与调试确认软件无错时,开发就告一段落,这时可以交付软件供用户使用,但是在软件的使用过程中还会面临更加漫长的工作,即软件维护。一般维护的工作有:更改使用中发现的错误;为适应实际环境而对程序进行修改;为满足新的需求而对程序作必要的改进等等。

七、归纳总结

通过两个星期的程序设计,让我更加深入的了解了C语言、C++语言和数据结构知识,在设计过程的一开始,每个人都是一筹莫展,虽然不是第

一次做实训,但是每次的实训都有新的难点需要突破,将C、C++和数据结

构综合在一起,一开始真的不知该如何下手,然后在设计的过程中,碰到

了许多问题,比如“{}”对应的不正确,语句的多余,在不同的编译环境

里,也会出现问题,有时候脑子一浑,找个之前写好的函数都很难找到,

有时候链接出错,还不知道是哪个里面出了问题,定义的函数太多,问题

找起来就显得很吃力,有好些时候都快做不下去了。还好有老师和同学的

帮助,我才可以解决这些拦路虎,完成这个程序,这个程序看起来不是很

复杂,我也不敢弄得很复杂,怕最后越写越乱。这个程序的设计也完全可

以认为不完美,程序界面也不够美观大方,所以今后在程序设计方面还需

要注意很多,可能还要花费更多的时间。虽然有不足,但是有不足才会有

进步,通过这次实践,让我对程序设计的兴趣又加深了一些,这为我今后

的学习奠定了很好的基础,我也会在今后好好完善自己,加强自己的动手

能力,让自己能写出更完善更漂亮的程序。

八、附源程序代码

#include //程序中要用到文件流类ofstream,ofstream是在这个中定义的#include

#include

#include //系统自带的字符串库函数,strcpy包含在这个头文件中

using namespace std;

struct Node

{

char data; // 节点数据域为字符型

Node *next;

Node(){ next = NULL;};

Node(char item,Node*link=NULL)

{

data=item;

next=link;

};

};

class LinkList //仅保留几个用得到的成员函数

{

protected:

Node *head;

Node *curPtr;

int count,curPosition;

Node *GetElemPtr(int position); // 返回指向第position个结点的指针

public:

LinkList();

int Length() const;

bool Empty() const;

void Traverse(); //遍历

void Traversetofile();

void Insert(int position, const char &e);

char GetElem(int position);

};

Node * LinkList::GetElemPtr(int position)

{

if (curPosition>position)

{

curPosition=0;

curPtr=head;

}

for (; curPosition

curPtr=curPtr->next;

return curPtr;

}

char LinkList::GetElem(int position)

{

Node *tmpPtr;

tmpPtr=GetElemPtr(position);

char e=tmpPtr->data;

return e;

}

LinkList::LinkList() //初始化链表

{

head=new Node; // 构造头指针,带表头结点的链表

curPtr=head;

curPosition=0;

count=0;

}

int LinkList::Length() const

{

return count;

}

bool LinkList::Empty() const

{

return head->next==NULL;

}

void LinkList::Traverse() //遍历链表

{

for (Node *tmpPtr=head->next;tmpPtr!=NULL;tmpPtr=tmpPtr->next)

{

cout<<(tmpPtr->data);

}

}

void LinkList::Traversetofile() //遍历文件

{

ofstream ofile3("result.txt"); //定义文件流对象,打开磁盘文件“result.txt”

if(!ofile3) //如果打开失败,ofile3返回0值

{

cout<<"cannot open result.txt\n";

return;

}

for(Node *tmpPtr=head->next;tmpPtr!=NULL;tmpPtr=tmpPtr->next)

{

ofile3<<(tmpPtr->data);

}

}

void LinkList::Insert(int position, const char &e)

{

Node *tmpPtr;

tmpPtr = GetElemPtr(position - 1);

Node *newPtr;

newPtr=new Node(e, tmpPtr->next);

tmpPtr->next=newPtr;

curPosition=position;

curPtr=newPtr;

count++;

}

struct HuffmanTreeNode // 哈夫曼树结点类

{

int weight;

unsigned int parent, leftChild, rightChild; // 双亲,左右孩子域

HuffmanTreeNode();

HuffmanTreeNode(int w, int p=0, int lChild=0, int rChild=0);

};

HuffmanTreeNode::HuffmanTreeNode() //初始化

{

parent = leftChild = rightChild = 0;

}

HuffmanTreeNode::HuffmanTreeNode(int w,int p,int lChild,int rChild) // 右孩子

{

weight = w; // 权

parent = p; // 双亲

leftChild = lChild; // 左孩子

rightChild = rChild; // 右孩子

}

class HuffmanTree

{

protected:

HuffmanTreeNode *nodes; // 存储结点信息,nodes[0]未用

char *LeafChars; // 叶结点字符信息,LeafChars[0]未用

string *LeafCharCodes; // 叶结点字符编码信息,LeafCharCodes[0]未用

int curPos; // 译码时从根结点到叶结点路径的当前结点

int num; // 叶结点个数

// 辅助函数:

void Select(int cur,int &r1,int &r2); // nodes[1 ~ cur]中选择双亲为0,权值最小的叶结点r1,r2

void CreatHuffmanTree(char ch[],int w[],int n);

public:

HuffmanTree(char ch[], int w[], int n); // 由字符,权值和字符个数构造哈夫曼树virtual ~HuffmanTree(); // 析构函数

string Encode(char ch); // 编码

LinkList Decode(string strCode); // 译码

};

void HuffmanTree::Select(int cur, int &r1, int &r2)

{

r1=r2=0; // 0表示空结点

for (int pos=1;pos<=cur;pos++)

{

if (nodes[pos].parent!=0) continue; // 只处理双亲为0的结点

if (r1==0)

{

r1=pos;

}

else

if(r2==0)

{

r2=pos;

}

else

if(nodes[pos].weight < nodes[r1].weight)

{

r1=pos;

}

else

if(nodes[pos].weight < nodes[r2].weight)

{

r2=pos;

}

}

}

void HuffmanTree::CreatHuffmanTree(char ch[], int w[], int n) //创建哈弗曼树

{

num=n; // 叶结点个数

int m=2*n-1; // 总结点个数

nodes = new HuffmanTreeNode[m+1]; // nodes[0]未用

LeafChars=new char[n+1]; // LeafChars[0]未用

LeafCharCodes=new string[n+1]; // LeafCharCodes[0]未用

int pos; // 临时变量

for (pos=1;pos<=n;pos++)

{ // 存储叶结点信息

nodes[pos].weight=w[pos-1]; // 权值

LeafChars[pos]=ch[pos-1]; // 字符

}

for (pos=n+1;pos<=m;pos++)

{ // 建立哈夫曼树

int r1, r2;

Select(pos-1,r1,r2);

nodes[r1].parent=nodes[r2].parent=pos; // r1,r2双亲为pos

nodes[pos].leftChild=r1; // r1为pos的左孩子

nodes[pos].rightChild=r2; // r2为pos的右孩子

nodes[pos].weight=nodes[r1].weight+nodes[r2].weight;//pos的权为r1,r2的权值之和}

for (pos = 1; pos <= n; pos++)

{ // 求n个叶结点字符的编码

LinkList charCode; // 暂存叶结点字符编码信息

for (unsigned int child=pos,parent=nodes[child].parent;parent!=0;child=parent,parent=nodes[child].parent) {

if (nodes[parent].leftChild==child)

charCode.Insert(1,'0');

else

charCode.Insert(1,'1');

}

for(int i=1;i<=charCode.Length();i++)

LeafCharCodes[pos].append(1,charCode.GetElem(i));//没有直接可以从链表为字符串赋值的函数,只能一个字符一个字符的追加过去

}

curPos=m;

}

HuffmanTree::HuffmanTree(char ch[],int w[], int n) //构造函数

{

CreatHuffmanTree(ch, w, n);

}

HuffmanTree::~HuffmanTree()

{

if (nodes!=NULL)

delete []nodes; // 释放结点信息

if (LeafChars!=NULL)

delete []LeafChars; // 释放叶结点字符信息

if (LeafCharCodes!=NULL)

delete []LeafCharCodes; // 释放叶结点字符编码信息

}

string HuffmanTree::Encode(char ch) //编码

{

for (int pos=1;pos<=num; pos++)

哈夫曼树编码译码实验报告(DOC)

数据结构课程设计设计题目:哈夫曼树编码译码

目录 第一章需求分析 (1) 第二章设计要求 (1) 第三章概要设计 (2) (1)其主要流程图如图1-1所示。 (3) (2)设计包含的几个方面 (4) 第四章详细设计 (4) (1)①哈夫曼树的存储结构描述为: (4) (2)哈弗曼编码 (5) (3)哈弗曼译码 (7) (4)主函数 (8) (5)显示部分源程序: (8) 第五章调试结果 (10) 第六章心得体会 (12) 第七章参考文献 (12) 附录: (12)

在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是哈夫曼编码。哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 第二章设计要求 对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,∑WiLi 恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。设计实现的功能: (1) 哈夫曼树的建立; (2) 哈夫曼编码的生成; (3) 编码文件的译码。

《哈夫曼编码译码课程设计》报告

计算机与信息工程系 《实践环节名称》报告 专业:计算机科学与技术 班级:******** 学号:********* 姓名:杨明英 报告完成日期:2011/6/10 指导教师:*** 评语: 成绩: 批阅教师签名:批阅时间:

目录 1.问题描述 (1) 2.基本要求 (1) 3.数据结构 (1) 4.总体设计 (1) 5.详细设计 (2) 5.1主函数 void main() (2) 5.2建立文件 void jianliwenjian() (3) 5.3输入原文 void luruyuanwen() (4) 5.4创建哈夫曼树 void chuangjian() (5) 5.5编码 void bianma() (6) 5.6对哈夫曼码译码 void yiwen() (7) 5.7保存译文 void baocunyiwen() (8) 5.8输出原文 void duquyuanwen() (9) 5.9输出原文编码void duqubianma() (10) 5.10输出译文 void duquyiwen() (11) 6.测试与调试 (11) 7.源程序清单 (8) 8.实验心得 (28)

1.问题描述 打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,设计一个哈夫曼编/译码系统。 2.基本要求 以每个字符出现的次数为权值,建立哈夫曼树,求出哈夫曼编码,对文件yuanwen 中的正文进行编码,将结果存到文件yiwen中,再对文件yiwen中的代码进行译码,结果存到textfile中。 3.数据结构 char CH[N]; //记录原文字符数组 char YW[N]; //记录译文字符数组 typedef char * Hcode[m+1]; //存放哈夫曼字符编码串的头指针的数组 typedef struct { char a; int num; }dangenode; //记录单个字符的类别和出现的次数 typedef struct { dangenode b[m]; int tag; }jilunode; //统计原文出现的字符种类和数量 typedef struct node //静态三叉的哈夫曼树的定义 { int weight; //结点的权值 int parent; //双亲的下标 int Lchild; //左孩子结点的下标 int Rchild; //右孩子结点的下标 }htnode,hn[M+1]; // hn是结构数组类型,0号单元不用 4.总体设计 功能函数模块划分 void main() //主函数 void jianliwenjian() //建立存储原文的文件yuanwen void luruyuanwen() //通过程序录入原文到文件yuanwen中 void min_2(hn ht,int n,int *tag1,int *tag2) //选择权值较小的两个结点 void chuangjian(jilunode * jilu,hn ht) //建立哈夫曼树 void bianma(jilunode * jilu,hn ht,Hcode hc,int n) //对原文进行编码 void bianmabaocun(Hcode hc,jilunode * jilu) //保存编码在文件yiwen中 void yiwen(Hcode hc,jilunode * jilu) //读取yiwen中的编码,并将其翻译为原文 void baocunyiwen() //将翻译的译文保存到文件textfile中 void duqubianma() //在编码文件yiwen中读取编码

数据结构 哈夫曼编码实验报告

实验报告 实验课名称:数据结构实验 实验名称:文件压缩问题 班级:20132012 学号:姓名:时间:2015-6-9 一、问题描述 哈夫曼编码是一种常用的数据压缩技术,对数据文件进行哈夫曼编码可大大缩短文件的传输长度,提高信道利用率及传输效率。要求采用哈夫曼编码原理,统计文本文件中字符出现的词频,以词频作为权值,对文件进行哈夫曼编码以达到压缩文件的目的,再用哈夫曼编码进行译码解压缩。 二、数据结构设计 首先定义一个结构体: struct head { unsigned char b; //记录字符 long count; //权重 int parent,lch,rch; //定义双亲,左孩子,右孩子 char bits[256]; //存放哈夫曼编码的数组 } header[512],tmp; //头部一要定设置至少512个,因为结 点最多可达256,所有结点数最多可 达511 三、算法设计 输入要压缩的文件读文件并计算字符频率根据字符的频率,利用Huffman 编码思想创建Huffman树由创建的Huffman树来决定字符对应的编码,进行文件的压缩解码压缩即根据Huffman树进行译码 设计流程图如图1.1所示。

图1.1 设计流程图 (1)压缩文件 输入一个待压缩的文本文件名称(可带路径)如:D:\lu\lu.txt 统计文本文件中各字符的个数作为权值,生成哈夫曼树;将文本文件利用哈夫曼树进行编码,生成压缩文件。压缩文件名称=文本文件名.COD 如:D:\lu\lu.COD 压缩文件内容=哈夫曼树的核心内容+编码序列 for(int i=0;i<256;i++) { header[i].count=0; //初始化权重 header[i].b=(unsigned char)i; //初始化字符 } ifstream infile(infilename,ios::in|ios::binary); while(infile.peek()!=EOF) { infile.read((char *)&temp,sizeof(unsigned char)); //读入一个字符 header[temp].count++; //统计对应结点字符权重 flength++; //统计文件长度 } infile.close(); //关闭文件 for(i=0;i<256-1;i++) //对结点进行冒泡排序,权重大的放在上面,编码时效率高 for(int j=0;j<256-1-i;j++) if(header[j].count

哈夫曼编码与译码的实现

数据结构课程设计评阅书

2011—2012学年第一学期 专业:信息管理与信息系统学号: 1021024016 姓名:万永馨 课程设计名称:数据结构课程设计 设计题目:哈夫曼编码与译码的实现 完成期限:自 2012 年 2 月 20 日至 2012 年 3 月 2 日共 2 周 设计依据、要求及主要内容(可另加附页): 该设计题目将按以下要求完成: 哈夫曼编码与译码是信息传输中应用的经典算法,运用C或VC++结合数据结构等基础知识,按 以下要求编程实现各种进制的转换。 任务要求:1)阐述设计思想,画出流程图;2)需要对哈夫曼编码/译码的相关原理有所了解,设计数 据结构,建立必要的信息数据文件(最好存储成外部文件),并分析完成用户所需的基本操作功能;3)实现给定信息的编码和译码功能;4)应有较好的界面设计,说明程序测试方法;5)按照格式要 求完成课程设计说明书。 设计要求: 1)问题分析和任务定义:根据设计题目的要求,充分地分析和理解问题,明确问题要求做什么?(而不是怎么做?)限制条件是什么?确定问题的输入数据集合。 2)逻辑设计:对问题描述中涉及的操作对象定义相应的数据类型,并按照以数据结构为中心的 原则划分模块,定义主程序模块和各抽象数据类型。逻辑设计的结果应写出每个抽象数据类型的定 义(包括数据结构的描述和每个基本操作的功能说明),各个主要模块的算法,并画出模块之间的调 用关系图; 3)详细设计:定义相应的存储结构并写出各函数的伪码算法。在这个过程中,要综合考虑系统 功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基 本操作的规格说明尽可能明确具体。详细设计的结果是对数据结构和基本操作做出进一步的求精, 写出数据存储结构的类型定义,写出函数形式的算法框架; 4)程序编码:把详细设计的结果进一步求精为程序设计语言程序。同时加入一些注解和断言, 使程序中逻辑概念清楚; 5)程序调试与测试:能够熟练掌握调试工具的各种功能,设计测试数据确保程序正确。调试正 确后,认真整理源程序及其注释,形成格式和风格良好的源程序清单和结果; 6)结果分析:程序运行结果包括正确的输入及其输出结果和含有错误的输入及其输出结果。算 法的时间、空间复杂性分析; 7)编写课程设计报告; 以上要求前三个阶段的任务完成后,将设计说明书的草稿交指导老师面审,审查合格方可进入 后续阶段的工作。设计工作结束,经指导老师验收合格后将设计说明书装订,并答辩。

哈夫曼编码译码系统实验报告,数据结构课程设计

安徽大学 数据结构课程设计报告项目名称:哈弗曼编/译码系统的设计 与实现 姓名:鉏飞祥 学号:E21414018 专业:软件工程 完成日期 2016/7/4 计算机科学与技术学院

1 .需求分析 1.1问题描述 ?问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站设计一个哈夫曼编译码系统。 1.2基本要求 (1) 输入的形式和输入值的范围; (2) 输出的形式; (3) 程序所能达到的功能。 1.基本要求 (1)初始化(Initialzation)。从数据文件DataFile.data中读入字符及每个字符的权值,建立哈夫曼树HuffTree; (2)编码(EnCoding)。用已建好的哈夫曼树,对文件ToBeTran.data中的文本进行编码形成报文,将报文写在文件Code.txt中; (3)译码(Decoding)。利用已建好的哈夫曼树,对文件CodeFile.data 中的代码进行解码形成原文,结果存入文件Textfile.txt中; (4)输出(Output)。输出DataFile.data中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.data及其报文Code.txt;输出CodeFile.data 及其原文Textfile.txt; 2. 概要设计 说明本程序中用到的所有抽象数据类型的定义。主程序的流程以及各程序模块之间的层次(调用)关系。 (1)数据结构 哈夫曼树的节点 struct huff

哈夫曼树的编码和译码

#include"stdafx.h" #include"stdio.h" #include"conio.h" #include #include #include using namespace std; #define maxbit 100 #define Maxvalue 2000//最大权值整数常量#define Maxleaf 100//最大叶子结点数 #define size 300//0、串数组的长度 static int n;//实际的叶子结点数 struct HNodeType { int weight; int parent; int lchild; int rchild; int ceng;//结点相应的层数 char ch;//各结点对应的字符 }; struct HCodeType { int bit[maxbit];//存放编码的数组 int start;//编码在数组中的开始位置}; static HNodeType *HuffNode;//定义静态指针HNodeType *init()//初始化静态链表 { HuffNode=new HNodeType[2*n-1]; for(int i=0;i<2*n-1;i++) { HuffNode[i].weight=0; HuffNode[i].parent=-1; HuffNode[i].lchild=-1; HuffNode[i].rchild=-1; HuffNode[i].ceng=-1; HuffNode[i].ch='0'; } return HuffNode; }

哈夫曼编码译码系统实验报告,数据结构课程设计报告

v .. . .. 安徽大学 数据结构课程设计报告项目名称:哈弗曼编/译码系统的设计 与实现 姓名:鉏飞祥 学号:E21414018 专业:软件工程 完成日期 2016/7/4 计算机科学与技术学院

1 .需求分析 1.1问题描述 ?问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站设计一个哈夫曼编译码系统。 1.2基本要求 (1)输入的形式和输入值的范围; (2)输出的形式; (3)程序所能达到的功能。 1.基本要求 (1)初始化(Initialzation)。从数据文件DataFile.data中读入字符及每个字符的权值,建立哈夫曼树HuffTree; (2)编码(EnCoding)。用已建好的哈夫曼树,对文件ToBeTran.data中的文本进行编码形成报文,将报文写在文件Code.txt中; (3)译码(Decoding)。利用已建好的哈夫曼树,对文件CodeFile.data中的代码进行解码形成原文,结果存入文件Textfile.txt中; (4)输出(Output)。输出DataFile.data中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.data及其报文Code.txt;输出CodeFile.data

及其原文Textfile.txt; 2. 概要设计 说明本程序中用到的所有抽象数据类型的定义。主程序的流程以及各程序模块之间的层次(调用)关系。 (1)数据结构 哈夫曼树的节点 struct huff { int weight; int parent; int l; int r; }; 哈夫曼编码的存储 struct huff *hufftree; (2)程序模块 选择1到i-1中parent为0且权值最小的两个下标 void Select(struct huff *HT, int n, int &s1, int &s2) 构建哈夫曼树: void huffmancoding(struct huff *ht,int *w,int n)

数据结构哈夫曼编码实验报告

数据结构实验报告 ――实验五简单哈夫曼编/译码的设计与实现本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结 构在实际问题中的应用。此实验可以作为综合实验,阶段性实验时可以选择其中的几 个功能来设计和实现。 一、【问题描述】 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编/码系统。系统应该具有如下的几个功能: 1、接收原始数据。 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat中。 2、编码。 利用已建好的哈夫曼树(如不在存,则从文件nodedata.dat中读入),对文件中的正文进行编码,然后将结果存入文件code.dat中。 3、译码。利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件textfile.dat中。 4、打印编码规则。 即字符与编码的一一对应关系。 二、【数据结构设计】 1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。 在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为: typedef struct { int weight;//结点权值 int parent; int lchild; int rchild; char inf; }HNodeType; 2、求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。 求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型: #define MAXBIT 10 typedef struct

哈夫曼编码与译码器_数据结构课程设计报告

沈阳航空航天大学 课程设计报告 课程设计名称:数据结构课程设计 课程设计题目:实现哈夫曼编码和译码器 院(系):计算机学院 专业:计算机科学与技术 班级:24010102 学号:2012040101082 姓名:尹伟和 指导教师:徐蕾

此页为任务书

目录 1.题目分析 (1) 1.1.题目重述 (1) 1.1.1.系统功能需求分析 (1) 2.程序设计 (2) 2.1.系统功能模块说明 (2) 2.1.1.系统功能模块结构 (2) 2.1.2.系统模块功能说明 (3) 2.2.数据结构说明 (3) 2.2.1.结构体定义说明 (3) 2.2.2.哈夫曼树 (4) 2.2.3.字符-哈夫曼编码对照表 (4) 2.3.函数说明 (4) 3.算法描述 (6) 3.1.哈夫曼树的构建 (6) 3.2.字符-哈夫曼编码对照表 (6) 3.3.编码 (6) 3.4.译码 (7) 4.程序测试 (9) 4.1.字符集输入 (9) 4.2.编码测试 (10) 4.3.译码测试 (11) 参考文献 (13) 附录(程序清单) (14)

沈阳航空航天大学课程设计报告 1.题目分析 1.1.题目重述 本次课程设计的目标是实现一个哈夫曼编码和译码器。该哈夫曼编码和译码器需要根据用户输入的字符集及相应字符出现的频率,对字符集所包含的字符进行哈夫曼编码。同时,作为编码器需要其对用户提供的明文字符串进行编码,使明文字符串变为二进制密文;作为译码器需要对用户提供的二进制密文进行译码,使二进制密文变为字符明文。 1.1.1.系统功能需求分析 通过对课程设计的题目分析,可以得出哈夫曼编码和译码器的功能需求,需求如下: 1)读取用户输入的字符集和相应字符出现的频率; 2)根据用户输入构建哈夫曼树; 3)根据哈夫曼树构建字符-哈夫曼编码对照表; 4)根据字符-哈夫曼编码对照表对明文字符串进行编码; 5)根据哈夫曼树对二进制密文进行译码。

完整word版哈夫曼编码译码器试验报告

中北大学 数据结构 课程设计说明书 学生姓名: 郝晨栋学号: 1021010933 软件学院学院: 软件开发与测试: 专业

哈夫曼编码/目题: 译码器 康珺教指导师 2011年12月20日 目录 1 问题描述.............................................................. 错误!未定义书签。 2 需求分析.............................................................. 错误!未定义书签。 3 概要设计 (1) 3.1抽象数据类型定义 (1) 3.2总体框图以及功能描述 (2) 4 详细设计 (2) 4.1数据类型的定义 (2) 4.2主要模块的算法描述 (3) 5 测试分析................................................................................................

4 6 课程设计总结 (6) 附录(源程序清单) (7) - 1 - 1 问题描述 1.设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。 (1) 将权值数据存放在数据文件(文件名为data.txt,位于当前目录中); (2) 分别采用动态和静态存储结构; 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树; (3) 编码:利用建好的哈夫曼树生成哈夫曼编码;输出编码; 设计要求: (1) 符合课题要求,实现相应功能; (2) 要求界面友好美观,操作方便易行; (3) 注意程序的实用性、安全性。 2 需求分析 编写此软件是为了实现一个利用哈夫曼算法的编码和译码系统。比如,再利用电报进行通讯时,需要将文字转换成由二进制的字符组成的字符串。比如需传送的电文为“A B A C C D A”假设将A,B,C,D分别编码为00、01、10、11.则上述电文遍为00010010101100,总长度为14位。但是在传送过程中,总希望长度能够尽可能的短,于是我们想采用长度不等的编码。但是这种编码必须遵循:任何一个字符的编码都不是另一个字符编码的前缀。 对此软件的要求:能够正确的使得对于输入的字符进行编码以及译码,并且是的在译码过程中不会出错,同时能够将编码以及译码的结果正确的存入文件当中。 3 概要设计 3.1抽象数据类型定义

哈夫曼编码实验报告

中南大学数据结构课程 姓名:刘阳 班级:信息0703 学号:0903070312 实验时间: 08.11.14 指导老师:赵颖

一、实验内容 根据输入的n 个带权结点,构造出哈夫曼树,并且把构造结果输出到屏幕。 二、实验说明 哈夫曼数,也称最优二叉树,是指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树。 设二叉树具有n 个带权值的叶结点,那么从根结点到各个叶结点的路径长度与相应结点权值的乘积之和叫做二叉树的带权路径长度WPL ,记作: WPL=k n k k L W *∑=1。在给定一组具有确定权值的叶结点,可以构造出不同的带权二 叉树。根据哈夫曼树的定义,一棵二叉树要使其WPL 值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。 在数据通讯中,经常需要将传送的文字转换成由二进制字符0,1组成的二进制串,我们称之为编码。例如,假设要传送的电文为ABACCDA ,电文中只含有A ,B ,C ,D 四种字符,若这四种字符采用下表所示的编码,则电文的代码为000010000100100111 000,长度为21。 在传送电文时,我们总是希望传送时间尽可能短,这就要求电文代码尽可能短。如果在编码时考虑字符出现的频率,让出现频率高的字符采用尽可能短的编码,出现频率低的字符采用稍长的编码,构造一种不等长编码,则电文的代码就可能更短。并且在建立不等长编码时,必须使任何一个字符的编码都不是另一个字符编码的前缀,以避免反译成原文时,编码出现多义性。 在哈夫曼编码树中,树的带权路径长度的含义是各个字符的码长与其出现次数的乘积之和,也就是电文的代码总长,所以采用哈夫曼树构造的编码是一种能使电文代码总长最短的不等长编码。 采用哈夫曼树进行编码,也不会产生上述二义性问题。因为,在哈夫曼树中,每个字符结点都是叶结点,它们不可能在根结点到其它字符结点的路径上,所以一个字符的哈夫曼编码不可能是另一个字符的哈夫曼编码的前缀,从而保证了译码的非二义性。

huffman编码译码实现文件的压缩与解压.

数据结构 课程设计 题目名称:huffman编码与解码实现文件的压缩与解压专业年级: 组长: 小组成员: 指导教师: 二〇一二年十二月二十六日

目录 一、目标任务与问题分析 (2) 1.1目标任务 (2) 1.2问题分析 (2) 二、算法分析 (2) 2.1构造huffman树 (2) 2.1.1 字符的统计 (2) 2.1.2 huffman树节点的设计 (2) 2.2构造huffman编码 (3) 2.2.1 huffman编码的设计 (3) 2.3 压缩文件与解压文件的实现 (3) 三、执行效果 (4) 3.1界面 (4) 3.2每个字符的编码 (4) 3.3操作部分 (5) 3.4文件效果 (6) 四、源程序 (7) 五、参考文献 (16)

huffman编码与解码实现文件的压缩与解压 一、目标任务与问题分析 1.1目标任务 采用huffman编码思想实现文件的压缩和解压功能,可以将任意文件压缩,压缩后也可以解压出来。这样即节约了存储空间,也不会破坏文件的完整性。 1.2问题分析 本问题首先应该是利用哈夫曼思想,对需要压缩的文件中的个字符进行频率统计,为了能对任意的文件进行处理,应该所有的文件以二进制的方式进行处理,即对文件(不管包含的是字母还是汉字)采取一个个的字节处理,然后根据统计的频率结果构造哈夫曼树,然后对每个字符进行哈夫曼编码,然后逐一对被压缩的文件的每个字符构建的新的哈夫曼编码存入新的文件中即得到的压缩文件。解压过程则利用相应的哈夫曼树及压缩文件中的二进制码将编码序列译码,对文件进行解压,得到解压文件。 二、算法分析 2.1构造huffman树 要利用哈夫曼编码对文本文件进行压缩,首先必须知道期字符相应的哈夫曼编码。为了得到文件中字符的频率,一般的做法是扫描整个文本进行统计,编写程序统计文件中各个字符出现的频率。由于一个字符的范围在[0-255]之间,即共256个状态,所以可以直接用256个哈夫曼树节点即数组(后面有节点的定义)空间来存储整个文件的信息,节点中包括对应字符信息,其中包括频率。 2.1.1 字符的统计 用结构体huffchar来存放文件字符的信息。其中有文件中不同字符出现的种类Count、字符data。 struct huffchar{ //存放读入字符的类; int Count;//字符出现的个数; char data;//字符; }; 函数实现: bool char_judge(char c)//判断字符出现的函数; void char_add(char c)//添加新出现的字符; void read_file_count() //文件的读取 2.1.2 huffman树节点的设计 用结构体huff_tree来存储结点信息,其中有成员频率weight、父亲节点parent、左儿子节点lchild、右儿子节点rchild。

数据结构哈夫曼编码译码器课程设计报告(有源程序)

JAVA语言实验报告 学院计算机工程学院班级计算1013 姓名 xxxx 学号 201081xxxx 成绩指导老师 xxxx 2012年09月03日

目录 目录 (1) 1 课程设计的目的和意义 (2) 2 需求分析 (3) 3 系统(项目)设计 (5) ①设计思路及方案 (5) ②模块的设计及介绍 (5) ③主要模块程序流程图 (8) 4 系统实现 (11) ①主调函数 (12) ②建立HuffmanTree (12) ③生成Huffman编码并写入文件 (15) ④电文译码 (16) 5 系统调试 (17) 参考文献 (21) 附录源程序 (22)

1 课程设计的目的和意义 在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。 哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个对应的字符的编码,这就是哈夫曼编码。 通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度尽可能最短,即采用最短码。 作为信息管理专业的学生,我们应该很好的掌握这门技术。在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。 在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。 在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见。同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。 数据结构课程具有比较强的理论性,同时也具有较强的可应用性和实践性。课程设计是一个重要的教学环节。我们在一般情况下都能够重视实验环节,但是容易忽略实验的总结,忽略实验报告的撰写。通过这次实验让我们明白:作为一名大学生必须严格训练分析总结能力、书面表达能力。需要逐步培养书写科学实验报告以及科技论文的能力。只有这样,我们的综合素质才会有好的提高。

哈夫曼编码译码器实验报告免费

哈夫曼编码译码器实验报告(免费)

————————————————————————————————作者:————————————————————————————————日期:

问题解析与解题方法 问题分析: 设计一个哈夫曼编码、译码系统。对一个ASCII编码的文本文件中的字符进行哈夫曼编码,生成编码文件;反过来,可将编码文件译码还原为一个文本文件。 (1)从文件中读入任意一篇英文短文(文件为ASCII编码,扩展名为txt); (2)统计并输出不同字符在文章中出现的频率(空格、换行、标点等也按字符处理);(3)根据字符频率构造哈夫曼树,并给出每个字符的哈夫曼编码; (4)将文本文件利用哈夫曼树进行编码,存储成压缩文件(编码文件后缀名.huf)(5)用哈夫曼编码来存储文件,并和输入文本文件大小进行比较,计算文件压缩率;(6)进行译码,将huf文件译码为ASCII编码的txt文件,与原txt文件进行比较。 根据上述过程可以知道该编码译码器的关键在于字符统计和哈夫曼树的创建以及解码。 哈夫曼树的理论创建过程如下: 一、构成初始集合 对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合 F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结 点,它的左右子树均为空。 二、选取左右子树 在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二 叉树的根结点的权值为其左右子树的根结点的权值之和。 三、删除左右子树 从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。 四、重复二和三两步, 重复二和三两步,直到集合F中只有一棵二叉树为止。 因此,有如下分析: 1.我们需要一个功能函数对ASCII码的初始化并需要一个数组来保存它们; 2.定义代表森林的数组,在创建哈夫曼树的过程当中保存被选中的字符,即给定报文 中出现的字符,模拟哈夫曼树选取和删除左右子树的过程; 3.自底而上地创建哈夫曼树,保存根的地址和每个叶节点的地址,即字符的地址,然 后自底而上检索,首尾对换调整为哈夫曼树实现哈弗曼编码; 4.从哈弗曼编码文件当中读入字符,根据当前字符为0或者1的状况访问左子树或者 右孩子,实现解码; 5.使用文件读写操作哈夫曼编码和解码结果的写入; 解题方法: 结构体、数组、类的定义: 1.定义结构体类型的signode 作为哈夫曼树的节点,定义结构体类型的hufnode 作为

哈夫曼编码与译码报告

一、设计思想 程序要求: 利用哈夫曼树对字符串进行编码,要求每个字符有自己唯一的编码。将得到的一串字串译成0、1编码后存到一个文件夹中,然后再从这个文件夹中读出这串编码进行解码。 实现方法: 输入一串字符,要求字符的区间为大写的26个英文字母,将获得的串字符用计算权值的函数(jsquanzhi())进行字符统计,统计出现的字符种数以及每种字符出现的次数,将该种字符出现的次数作为它的权值。将出现的字符的权值和该字符依次分别赋给两个结构体HT和HC,利用HT(节点)权值的大小建立哈夫曼树,首先用选择函数select()函数选择两个权值最小的字符作为叶子节点,创建一个新的节点作为这两个叶节点的父节点,被选中的节点给他的HT[i].parent赋值是他下次不再被选中,父节点的权值为,子节点的权值之和。然后将该将父节点放入筛选区中,再进行选择(被选过的不再被使用),直到所有的节点都被使用,这样一个哈夫曼树就被建立了。根据每个字符在哈夫曼书中的位置来编译每个字符的0、1密文代码,从叶节点判断该叶节点是其父节点的左右字左字为‘0’,右子为‘1’,在判断父节点是上级父节点的左右子直至根节点,将生成的0、1字符串按所表示的字符倒序存入HC相应的字符的bins[]数组。 重新一个一个字符的读取输入的字符串,按照字符出现的顺序将它转为0、1代码并存到一个txt文件夹中去。解码时从文件夹中,一个一个字符的读出那串0、1代码赋给一个临时字符串cd[],用该字符串与每个字符的HC[i].bins密文比较,直到与一个字符的密文相同时,译出该字符,将字符存放在临时字符数组tempstr[]中,清空临时字符串继续读取0、1代码进行翻译,直至文件密文结束为止。于是就得到了原先被加密的那串字符串。

哈夫曼编码实验报告

二、实验内容 1.根据给出的字符以及这些字符的使用频率构建哈夫曼树。 2.根据哈夫曼树对字符进行哈夫曼编码,并保存这些编码。 三、实验原理、方法和手段 试构造出问题模型,并编程实现这一问题的求解。根据实验内容编程,上机调试、得出正确的运行程序;编译运行程序,观察运行情况和输出结果。 六、实验步骤 1. 建立哈夫曼树的存储结构和哈夫曼编码的存储结构。 2. 建立哈夫曼树的函数; 3. 哈夫曼编码的函数; 4.哈夫曼编码的解码函数 5. 设计测试用例进行测试。 七、实验报告 记录数据结构与算法设计的过程及实验步骤、上机过程中遇到的困难及解决办法、遗留的问题、托福考位意见和建议等。格式见实验报告模板。测试数据及测试结果请在上交的资料中写明。

#include #include #define N 50#define M 2*N-1 const int INF=1e9+7;typedef struct//哈夫曼树的存储结构 { char data[6]; double weight; int parent; int lchild; int rchild; } HTNode;typedef struct//存放哈夫曼码存储结构 { char cd[N]; int start; } HCode;void CreateHT(HTNode ht[],int n0) //建立哈夫曼树的函数{ int i,k,lnode,rnode; double min1,min2; for (i=0;i<2*n0-1;i++) ht[i].parent=ht[i].lchild=ht[i].rchild=-1; for (i=n0;i<=2*n0-2;i++) {

哈夫曼编码和译码系统

通达学院 算法与数据结构程序设计 题目:哈夫曼编码和译码系统 专业 学生姓名 班级学号 指导教师 指导单位 日期

教师评语 同学出勤率(满勤、较高、一般,较低),学习态度(端正、较端正、一般、较差),程序设计基础(好、较好、一般、较差),演示程序(已经、没有)达到了基本要求,算法设计(好、较好、一般),界面友好程度(好、较好、一般),答辩过程中回答问题(准确、较准确、错误率较高),撰写报告格式(规范、一般)、内容(丰满、简单)、表述(清晰、一般、不清楚),(圆满、较好、基本)完成了课题任务。 教师签名: 年月日 成绩评定 备注

一、题目要求: 题 目 :哈夫曼编码和译码系统 基本要求: (1) 能输入字符集和各字符频度建立哈夫曼树; (2) 产生各字符的哈夫曼编码,并进行解码。 提高要求: (1) 能设计出简捷易操作的窗口界面; (2) 编码和译码存储在文件中。 二、需求分析: 2.1基本思想 根据,哈夫曼的定义,一棵二叉树要使其带权路径长度最小,必须使权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点.依据这个特点便提出了哈夫曼算法,其基本思想是: (1) 初始化:由给定的n 个权值{w 1, w 2,…, w n }构造n 棵只有一个根结点的二叉树,从而得到一个二叉树集合F={ T 1,T 2,…,T n }; (2) 选取与合并:在F 中选取根结点的权值最小的两棵二叉树分别作为左、右子树构造一颗新的二叉树,这棵新二叉树的根结点的权值为其左、右子树根结点的权值之和; (3) 删除与加入:在F 中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到F 中; (4) 重复(2)、(3)两步,当集合F 中只剩下一棵二叉树时,这棵二叉树便是哈夫曼树. 2.2存储结构 在由哈夫曼算法构造的哈夫曼树中,非叶子结点的度均为2,根据二叉树的性质可知,具有n 个叶子结点的哈夫曼树共有2n-1个结点,其中有n-1个非叶子结点,它们是在n-1次的合并过程中生成的.为了便于选取根结点权值最小的二叉树以及合并操作,设置一个数组HuffmanNode[2n-1]保存哈夫曼树中各结点的信息,数组元素的结点结构如图所示. 图 哈夫曼树的结点结构 其中: weight parent lchild rchild i nf

哈夫曼编码译码器---课程设计报告

目录 目录 (2) 1课程设计的目的和意义 (3) 2需求分析 (4) 3概要设计 (4) 4详细设计 (8) ¥ 5调试分析和测试结果 (11) 6总结 (12) 7致谢 (13) 8附录 (13) 参考文献 (20) .

| ; 1 课程设计目的与意义 在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。 哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个对应的字符的编码,这就是哈夫曼编码。 通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度尽可能最短,即采用最短码。 作为计算机专业的学生,我们应该很好的掌握这门技术。在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。 ( 在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们

可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。 在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见。同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。 数据结构课程具有比较强的理论性,同时也具有较强的可应用性和实践性。课程设计是一个重要的教学环节。我们在一般情况下都能够重视实验环节,但是容易忽略实验的总结,忽略实验报告的撰写。通过这次实验让我们明白:作为一名大学生必须严格训练分析总结能力、书面表达能力。需要逐步培养书写科学实验报告以及科技论文的能力。只有这样,我们的综合素质才会有好的提高。 2 需求分析 课题:哈夫曼编码译码器 ) 问题描述:打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,对每一个字符进行编码,编码完成后再对其编码进行译码。问题补充:1. 从硬盘的一个文件里读出一段英语文章; 2. 统计这篇文章中的每个字符出现的次数; 3. 以字符出现字数作为权值,构建哈夫曼树,并将哈夫曼树的存储 结构的初态和终态进行输出; 4. 对每个字符进行编码并将所编码写入文件然后对所编码进行破 译。 具体介绍:在本课题中,我们在硬盘中预先建立一个文档,在里面编辑一篇文章。然后运行程序,调用函数读出该文章,显示在界面;再调用函数对该文章的字符种类进行统计,并对每个字符的出现次数进行统计,并且在界面上显示;然后以每个字符出现次数作为权值,调用函数构建哈夫曼树;并调用函数将哈夫曼的存储结构的初态和终态进行输出。然后调用函数对哈夫曼树进行编码,调用函数将编码写入文件;再调用对编码进行译码,再输出至界面。至此,整个工作就完成了 3 概要设计。

相关文档
最新文档