哈弗曼编码课程设计实验报告
- 格式:doc
- 大小:94.50 KB
- 文档页数:19
目录
一、实训要求 (2)
二、课题分析和设计 (2)
1、基本需求分析……………………………………………………………………2,3
2、对应的类………………………………………………………………................3,4,5
三、主要功能界面 (5)
1、主界面 (5)
2、读取文章并对字符编码 (5)
3、哈弗曼编码信息 (6)
4、文章编码 (6)
5、文章译码 (6)
6、错误处理 (7)
四、总结(课设心得体会) (7)
五、附录(主要函数代码)………………………………………………………………7~14
一、实训要求
1、输入为:一段中文或英文的文章的文件名。
2、读取文章的字符信息。
3、对字符进行权值的计算。
4、根据权值构造哈弗曼树。
5、生成对应的编码。
6、输出为:原文章的编译(译文)。
7、根据已经生成的编码表,输入任意的译文可以得到原文。
二、课题分析和设计
1.基本需求分析:
(1)在通信过程中,为了提高信道利用率,缩短信息传输时间降低传输成本,需要一编译码器。
(2)此哈弗曼编码译码器应具有编码译码的双向功能,即在发送端通过编码系统对传入的数据进行编码。
(3)在接收端将数据译码,将具有两项功能的编码译码器用于双工信道就可满足,双工信道的双向编译功能。
(4)输入某段报文是,系统将自己完成编译输出。
(5)、程序设计流程:
<1>文字表述:
开始进入功能选择界面,包含五种操作
(1)读取文章并对字符编码。
(2)哈夫曼编码信息。
(3)文章编码。
(4)文章译码。
(5)退出程序。
<2>操作:
(1)给定一篇文章,统计字符出现的概率,并根据概率建立哈弗曼树,并利用哈弗曼树对字符进哈夫曼编码。
(2)显示哈弗曼编码信息,包括字符和其哈弗曼编码。
(3)对文章进行译码,显示译码信息,并保存。
(4)对文章进行译码,显示并保存。
<3>流程图:
2、对应的类:
<1>定义类:
class Element //结点类{
public:
char name;//字符名
int weight;//字符权值
int lchild;//左孩子
int rchild;//右孩子
int parent;//父结点
Element()
{
weight = 0;
lchild = -1;
—
rchild = -1;
parent =-1;
}
~Element(){}
};
<2>定义字符和出现的次数:
class Name //字符类
{
public:
char pname;//字符名
int num;//字符出现的次数
double lweight;//字符的权值
Name()
{
num = 0;
lweight = 0;
}
~Name(){}
};
<3>定义字符总类总数和存储信息:
class GetName //关于字符类
{
public:
char file_name[max2];//文件名
int n; //字符的种类
int sum; //字符的总数
Name letter[max1]; //存储字符信息的类的数组
GetName()
{
sum = 0;
n = 0;
}
};
<4>定义编码类:
class CodeNode//编码类
{
public:
char ch; //存储字符
char save_code[max1]; //存储编码
};
—
<5>主要功能实现类:
class Function
{
public:
GetName L;
int fn; //定义哈夫曼数组大小
Element HuffmanT[max3]; //哈夫曼数组
CodeNode Code[max1]; //字符编码数组
Function()
{
fn = 0;
}
};
三、主要功能界面:
1、主界面:
2、读取文章并对字符编码:
3、哈弗曼编码信息:
4、文章编码:
5、文章译码:
6、错误处理:
四、总结(课设心得体会):
三周的课程设计结束了,在这次的课程设计中不仅检验了我所学习的知识,也培养了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情。
在设计过程中,与同学分工设计,和同学们相互探讨,相互学习,相互监督。
学会了合作,学会了运筹帷幄,学会了宽容,学会了理解,也学会了做人与处世。
课程设计是我们专业课程知识综合应用的实践训练,着是我们迈向社会,从事职业工作前一个必不少的过程.”千里之行始于足下”,通过这次课程设计,我深深体会到这句千古名言的真正含义.我今天认真的进行课程设计,学会脚踏实地迈开这一步,就是为明天能稳健地在社会大潮中奔跑打下坚实的基础. 通过这次课程设计,本人在多方面都有所提高。
在这次设计过程中,体现出自己单独设计模具的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。
六、附录(源代码):
#include <iostream>
#include <fstream>
#include <string.h>
#include <windows.h>
—
#define max1 150
#define max2 50
#define max3 256
using namespace std;
class Element //结点类
{
public:
char name;//字符名
int weight;//字符权值
int lchild;//左孩子
int rchild;//右孩子
int parent;//父结点
Element()
{
weight = 0;
lchild = -1;
rchild = -1;
parent =-1;
}
~Element(){}
};
class CodeNode//编码类
{
public:
char ch; //存储字符
char save_code[max1]; //存储编码
};
class Name //字符类
{
public:
char pname;//字符名
int num;//字符出现的次数
double lweight;//字符的权值
Name()
{
num = 0;
lweight = 0;
}
~Name(){}
};
—
class GetName //关于字符类
{
public:
char file_name[max2];//文件名
int n; //字符的种类
int sum; //字符的总数
Name letter[max1]; //存储字符信息的类的数组
GetName()
{
sum = 0;
n = 0;
}
void GetWeight()//得到字符的权值
{
for (int i = 0; i < n; i++)
{
letter[i].lweight = (double) letter[i].num / sum; //出现的次数除总数得到权值}
}
int ReadLetter()
{
ifstream input;
cout << "请输入文件名:" << endl;
cin >> file_name;
input.open(file_name); //打开文件
if (input.fail())
{
cout << "该文件不存在!" << endl;
return 0;
}
char ch;
ch = input.get();
letter[0].pname = ch;
letter[0].num++;
sum++;
while (!input.eof())//读取文件中的所有字符
{
int tag = 0;
ch = input.get();
for (int i = 0; i < n + 1; i++)
{
if (letter[i].pname == ch)
—
{
letter[i].num++;
sum++;
tag = 1;
}
}
if (tag == 0)
{
n++;
letter[n].pname = ch;
letter[n].num++;
sum++;
}
}
sum--;
input.close();
GetWeight(); //得到字符权值
}
};
class Function
{
public:
GetName L;
int fn; //定义哈夫曼数组大小
Element HuffmanT[max3]; //哈夫曼数组
CodeNode Code[max1]; //字符编码数组
Function()
{
fn = 0;
}
void CharHuffmanTCoding()//编码功能实现
{
int i, f, c;
char *cd = new char [L.n+1]; //暂时存储编码的数组
int start; //编码读取起始位置
cd[L.n] = '\0';
for (i = 0; i < L.n; i++)
{
Code[i].ch = HuffmanT[i].name; //字符信息
start = L.n; //起始位置
c = i;
while ((f = HuffmanT[c].parent) >= 0)
{
—
if (HuffmanT[f].lchild == c)//如果为左孩子,为‘0’
{
cd[--start] = '0';
}
else//如果为右孩子,为‘1’
{
cd[--start] = '1';
}
c = f;
}
strcpy(Code[i].save_code, &cd[start]); //将结果存入对应的编码数组中}
}
void OutputHuffmanTCode()
{
cout << "哈夫曼编码:" << endl;
cout << "——————————————————————" << endl;
cout << "字符\t\t哈夫曼编码" << endl;
for (int i = 0; i < L.n; i++)//输出字符,哈夫曼编码
{
cout << "——————————————————————" << endl;
cout << HuffmanT[i].name << "\t"<< "\t";
cout << Code[i].save_code;
cout << endl;
}
cout << "——————————————————————" << endl;
}
void InitHT()//哈夫曼初始化
{
L.ReadLetter();
fn = (L.n)*2 - 1;
for (int i = 0; i < fn; i++)
{
if (i < L.n)
{
HuffmanT[i].name = L.letter[i].pname;
HuffmanT[i].weight = L.letter[i].lweight;
}
}
}
void Select_2Min(int m, int &p1, int &p2)//选择最小的两个节点
{
int i;
double m1, m2;
m1 = m2 = 1;
p1 = p2 = -1;
for (i = 0; i < m; i++)
{
if (HuffmanT[i].parent == -1 && HuffmanT[i].weight < m1)//找出未访问过的权值最小节点
{
m2 = m1;
p2 = p1;
m1 = HuffmanT[i].weight;
p1 = i;
}
else if (HuffmanT[i].parent == -1 && HuffmanT[i].weight < m2)//找出未访问过的权值第二小结点
{
m2 = HuffmanT[i].weight;
p2 = i;
}
}
}
void CreatHT()//建立哈夫曼树//核心
{
int i, p1, p2;
InitHT();
for (i = L.n; i < fn; i++)
{
Select_2Min(i, p1, p2);
HuffmanT[p1].parent = HuffmanT[p2].parent = i;
HuffmanT[i].weight = HuffmanT[p1].weight + HuffmanT[p2].weight;
HuffmanT[i].lchild = p1;
HuffmanT[i].rchild = p2;
}
}
int OutArticleCode()//显示文章编码
{
ifstream input;
input.open(L.file_name);
if (input.fail())
{
cout << "文件不存在!" << endl;
return 0;
}
char ch;
cout << "文章编码如下:" << endl;
while (!input.eof())
{
ch = input.get();
for (int i = 0; i < L.n; i++)
{
if (Code[i].ch == ch)
cout << Code[i].save_code;
}
}
cout << endl;
input.close();
}
int SaveArticleCode()//保存文章编码
{
ofstream output;
ifstream input;
char namef1[max2];
input.open(L.file_name);
if (input.fail())
{
cout << "该文件不存在!" << endl;
return 0;
}
cout << "请输入保存文章编码的文件名:" << endl;
cin >> namef1;
output.open(namef1);
char ch;
while (!input.eof())
{
ch = input.get();
for (int i = 0; i < L.n; i++)
{
if (Code[i].ch == ch)
{
for (int j = 0; j < strlen(Code[i].save_code); j++)
{
output.put(Code[i].save_code[j]);
}
}
}
}
input.close();
output.close();
cout << "保存完毕!" << endl;
—
}
int OutTransCode() //文章译码操作
{
ifstream input;
char namef[max2];
cout << "请输入保存文章编码的文件名:" << endl;
cin >> namef;
input.open(namef);
if (input.fail())
{
cout << "该文件不存在!" << endl;
return 0;
}
char ch;
ch = input.get();
int c = 2 * L.n - 2;
while (!input.eof())
{
if (ch == '0')//遇0搜索左子树
{
if (HuffmanT[c].lchild >= 0){
c = HuffmanT[c].lchild;
}
if (HuffmanT[c].lchild == -1)//判断是否到叶子
{
cout << HuffmanT[c].name; //输出字符
c = 2 * L.n - 2; //返回根节点
}
}
if (ch == '1')//遇1搜索右子树
{
if (HuffmanT[c].rchild >= 0)
{
c = HuffmanT[c].rchild;
}
if (HuffmanT[c].rchild == -1)//判断是否到叶子
{
cout << HuffmanT[c].name; //输出字符
c = 2 * L.n - 2; //返回根节点
}
}
ch = input.get();
}
cout << endl;
—
input.close();
}
int SaveTransCode()//保存文章译码
{
ofstream output;
ifstream input;
char namef[max2];
char namef1[max2];
cout << "请输入文章编码所在的文件名:" << endl;
cin >> namef;
input.open(namef);
if (input.fail())
{
cout << "该文件不存在!" << endl;
return 0;
}
cout << "请输入保存文章译码的文件名:" << endl;
cin >> namef1;
output.open(namef1);
char ch;
ch = input.get();
int c = 2 * L.n - 2;
while (!input.eof())
{
if (ch == '0')
{
if (HuffmanT[c].lchild >= 0)
{
c = HuffmanT[c].lchild;
}
if (HuffmanT[c].lchild == -1)
{
output.put(HuffmanT[c].name);
c = 2 * L.n - 2;
}
}
if (ch == '1')
{
if (HuffmanT[c].rchild >= 0)
{
c = HuffmanT[c].rchild;
}
if (HuffmanT[c].rchild == -1) {
output.put(HuffmanT[c].name);
—
c = 2 * L.n - 2;
}
}
ch = input.get();
}
input.close();
output.close();
cout << "保存完毕!" << endl;
}
};
int main()
{
Function *a = new Function;
while (1) //主界面显示
{
cout<<"
************************************"<<endl;
cout<<" *******欢迎进入编/译码系统**********"<<endl;
cout<<"
************************************"<<endl;
cout<<endl;
cout<<" *******功能如下:*******************"<<endl;
cout<<" *******1.读取文章并对字符编码*******"<<endl;
cout<<" *******2.哈夫曼编码信息*************"<<endl;
cout<<" *******3.文章编码*******************"<<endl;
cout<<" *******4.文章译码*******************"<<endl;
cout<<" *******5.退出程序*******************"<<endl;
cout<<endl;
char ch;
cout << "====>>请选择功能:";
cin>> ch;
switch (ch)
{
case '1'://读取文章并对字符编码
{
delete a;
a = new Function;
system("cls");
a->CreatHT();
a->CharHuffmanTCoding();
cout << "操作完毕!" << endl;
system("pause");
—
system("cls");
break;
}
case '2'://哈夫曼编码信息
{
system("cls");
a->OutputHuffmanTCode();
system("pause");
system("cls");
break;
}
case '3'://文章编码
{
system("cls");
while (1)
{
cout << endl;
cout << "========>>1.显示文章编码" << endl;
cout << "========>>2.保存文章编码" << endl;
cout << "========>>3.返回上一界面" << endl;
char ch1;
cout << endl << "===>>请选择功能:";
cin >> ch1;
switch (ch1)
{
case '1'://显示文章编码
{
system("cls");
a->OutArticleCode();
system("pause");
system("cls");
continue;
}
case '2'://保存文章编码
{
system("cls");
a->SaveArticleCode();
system("pause");
system("cls");
continue;
}
case '3'://返回上一界面
{
break;
}
default:
{
system("cls");
cout << "输入错误,请重新输入!" << endl;
continue;
}
}
system("cls");
break;
}
break;
}
case '4'://文章译码
{
system("cls");
while (1)
{
cout << endl;
cout << "========>>1.显示文章编码的译码" << endl;
cout << "========>>2.保存文章编码的译码" << endl;
cout << "========>>3.返回上一界面" << endl;
char ch1;
cout << endl << "===>>请选择功能:";
cin >> ch1;
switch (ch1)
{
case '1'://显示文章编码的译码
{
system("cls");
a->OutTransCode();
system("pause");
system("cls");
continue;
}
case '2'://保存文章编码的译码
{
system("cls");
a->SaveTransCode();
system("pause");
system("cls");
continue;
}
case '3'://返回上一界面
{
break;
}
default:
{
system("cls");
cout << "输入错误,请重新输入!" << endl;
continue;
}
}
system("cls");
break;
}
break;
}
case '5'://退出程序
{
return 0;
}
default:
{
system("cls");
cout << "功能选择错误,请重新输入!" << endl;
break;
}
}
}
return 0;
}。