无损压缩编码实验
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
无损压缩编码实验
实验报告
一、实验题目:无损压缩编码实验
二、实验要求:任选一种无损编码式,通过C++编程实现。
(1)字符串的输入是手工输入的。
(2)通过程序实现编码,最终在屏幕上现实编码结果。
三,实验分析
采用霍夫曼编码实现无损压缩编码,从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码,并算出平均码长。
四,主要编码原理
五,源程序代码
#include <iostream>
using namespace std;
class HuffmanTree//霍夫曼树结构
{public:
unsigned int Weight, Parent, lChild, rChild;
};
typedef char **HuffmanCode;
void Select(HuffmanTree* HT,int Count,int *s2,int *s1)//从结点集合中选出权值最小的两个结点
{
unsigned int temp1=0;
unsigned int temp2=0;
unsigned int temp3;
for(int i=1;i<=Count;i++)
{
if(HT[i].Parent==0)
{
if(temp1==0)
{
temp1=HT[i].Weight;
(*s1)=i;
}
else
{ if(temp2==0)
{temp2=HT[i].Weight;
(*s2)=i;
if(temp2<temp1)
{
temp3=temp2;
temp2=temp1;
temp1=temp3;
temp3=(*s2);
(*s2)=(*s1);
(*s1)=temp3;
}
}
else
{
if(HT[i].Weight<temp1)
{
temp2=temp1;
temp1=HT[i].Weight;
(*s2)=(*s1);
(*s1)=i;
}
if(HT[i].Weight>temp1&&HT[i].Weight<temp2)
{
temp2=HT[i].Weight;
(*s2)=i;
}
}
}
}
}
}
void HuffmanCoding(HuffmanTree * HT, HuffmanCode * HC,int *Weight,int Count)//霍夫曼编码函数
{
int i;
int s1,s2;
int TotalLength;
char* cd;
unsigned int c;
unsigned int f;
int start;
if(Count<=1) return;
TotalLength=Count*2-1;
HT = new HuffmanTree[(TotalLength+1)*sizeof(HuffmanTree)];
for(i=1;i<=Count;i++)
{
HT[i].Parent=0;//父节点
HT[i].rChild=0;//左孩子
HT[i].lChild=0;//右孩子
HT[i].Weight=(*Weight);
Weight++;
}
for(i=Count+1;i<=TotalLength;i++)
{
HT[i].Weight=0;
HT[i].Parent=0;
HT[i].lChild=0;
HT[i].rChild=0;
}
//建造霍夫曼树
for(i=Count+1;i<=TotalLength;++i)
{
Select(HT, i-1, &s1, &s2);
HT[s1].Parent = i;
HT[s2].Parent = i;
HT[i].lChild = s1;
HT[i].rChild = s2;
HT[i].Weight = HT[s1].Weight + HT[s2].Weight;
}
//输出霍夫曼编码
(*HC)=(HuffmanCode)malloc((Count+1)*sizeof(char*));
cd = new char[Count*sizeof(char)];
cd[Count-1]='\0';
for(i=1;i<=Count;++i)
{
start=Count-1;
for(c = i,f = HT[i].Parent; f != 0; c = f, f = HT[f].Parent)
{
if(HT[f].lChild == c)
cd[--start]='0';
else
cd[--start]='1';
(*HC)[i] = new char [(Count-start)*sizeof(char)];
strcpy((*HC)[i], &cd[start]);
}
}
delete [] HT;
delete [] cd;
}
int LookFor(char *str, char letter, int count)//在字符串中查找某个字符,如果找到,则返回其位置
{ int i;
for(i=0;i<count;i++)
{
if(str[i]==letter) return i;
}
return -1;
}
void Quanzhi(char *Data,int Length,char **WhatLetter,int **Weight,int *Count)//
计算权值并输出
{
int i;
char* Letter = new char[Length];
int* LetterCount = new int[Length];
int AllCount=0;
int Index;
int Sum=0;
float Persent=0;
for(i=0;i<Length;i++)
{
if(i==0)
{
Letter[0]=Data[i];
LetterCount[0]=1;
AllCount++;
}
else
{
Index=LookFor(Letter,Data[i],AllCount);
if(Index==-1)
{
Letter[AllCount]=Data[i];
LetterCount[AllCount]=1;
AllCount++;
}
else
{LetterCount[Index]++;
}
}
}
for(i=0;i<AllCount;i++)//计算平均码长
{
Sum=Sum+LetterCount[i];
}
(*Weight) = new int[AllCount];
(*WhatLetter) = new char[AllCount];
for(i=0;i<AllCount;i++)
{
Persent=(float)LetterCount[i]/(float)Sum;
(*Weight)[i]=(int)(100*Persent);
(*WhatLetter)[i]=Letter[i];
}
(*Count)=AllCount;
delete [] Letter;
delete [] LetterCount;
}
int main()//主函数调用
{
HuffmanTree * HT = NULL;
HuffmanCode HC;
char Data[100];//储存输入的字符串
char *Letter;
int *Weight;
int Count;
cout<<"**********欢迎使用霍夫曼编码器********"<<endl; cout<<"请输入一行字符串:"<<endl;
cin>>Data;
cout<<endl;
Quanzhi(Data,strlen(Data),&Letter, &Weight,&Count); HuffmanCoding(HT, &HC, Weight, Count);
cout<<"字符出现频率和编码结果"<<endl;
double K=0;
double L;
char P[100];
for(int i = 0; i<Count; i++)
{
cout<<Letter[i]<<" ";//字符cout<<Weight[i]<<"%\t";//出现频率cout<<HC[i+1]<<endl;//霍夫曼码strcpy(P,HC[i+1]);
L=strlen(P);
K=K+L*Weight[i]/100;
}
cout<<"平均码长"<<K;
cout<<endl;
system("pause");
return 0;
}
六,测试结果
输入字符串“jjjdddeielsl”
七,实验总结
通过本次实验,尤其在自己对程序的调试过程中,感觉对树的存储结构,终结状态,还有编码,译码的过程都有了比较清晰的认识。
对于霍夫曼的编码算法过程有了更深的理解,对霍夫曼树的构造,二叉树的遍历更加熟悉。
实验过程出现了一些问题,通过查阅资料,最终顺利解决。