霍夫曼编码
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
else if(myHuffmantree[j].rd==x)
{
numOfCode[h++]=1;
}
}
cout<<" "<<allchar[i]<<" : ";
int x=0;
coder[i].len=h;
coder[i].ch=allchar[i];
for(int k=h-1;k>=0;k--)
a:01
c:010
d:011
现在给你一段编码0110101,要求将其译码!
按照上面介绍的方法我们可以直到:
编码的前三个字符是且仅是d的编码,所以011译码为d,依次译码可得整串的译码结果为daa
霍夫曼编码源代码:
#include<iostream>
#include<cstring>
#include<algorithm>
{
myToCode[h].ch=iter->first;
allchar[h]=iter->first;
weightOfToCode[h]=iter->second;
myToCode[h++].num=iter->second;
}
nNode=h-1; //叶子节点个数
cout<<"----------------------字符统计如下--------------------------------------"<<endl;
intweightOfToCode[100000] ; //字符串的权值!
HuffmantreemyHuffmantree[1000000]; //霍夫曼树(数组模拟)
char allchar[1000000]; //所哟出现过的字符
mycode coder[1000000]; //字符与对应的编码
myHuffmantree[i].parent=i;
}
for(i=1;i<=totalNode;i++)
{
printf("节点:%3d权值:%3d左节点:%3d右节点:%3d父节点:%3d \n",i,myHuffmantree[i].weight,myHuffmantree[i].ld,myHuffmantree[i].rd,myHuffmantree[i].parent);
}
}
void Code() //编码
{
inti,j;
intnumOfCode[100000];
cout<<"--------------------------各字符编码结果如下----------------------------"<<endl;
if(Len==1)
{
cout<<toCode[0]<<" : "<<"0\n";
霍夫曼树:
下面是字符串agdfaghdabsb的霍夫曼编码的霍夫曼树:
字符串:agdfaghdabsb
出现的字符
字符出现的次数
a
3
g
2
d
2
f
1
h
1
b
2
s
1
合计
12
由上面的霍夫曼树可知各个字符的编码如下:
a: 01
b:010
d:011
f:100
g:101
h:110
s:111
所以整个串的编码为:
011010111000110111001101010111010
int sign2=2; //次小值的下标
for(i=1;i<=totalNode;i++)
{
if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点
{
if(myHuffmantree[i].weight<min1)
{
min1=myHuffmantree[i].weight;
{
coder[i].s[x++]=numOfCode[k];
printf("%d",numOfCode[k]);
}
cout<<endl;
}
}
void select(int&a,int&b) //选择两个权值最小的节点
{Leabharlann Baidu
int i;
int min1=INF;
int min2=INF;
int sign1=1; //最小值的下标
#include<map>
using namespace std;
#define INF 0x7fffffff //无穷大
structHuffmantree //霍夫曼树的节点
{
int weight;
intparent,ld,rd;
};
structmyNode
{
charch;
intnum;
};
structmycode //字符和其对应的编码
return ;
}
for(i=1;i<=nNode;i++)
{
j=i;
int h=0;
while(myHuffmantree[j].parent!=j)
{
int x=j;
j=myHuffmantree[j].parent;
if(myHuffmantree[j].ld==x)
{
numOfCode[h++]=0;
map<char,int>myMap;
for(i=0;i<len;i++) //统计字符串中各字符出现的频次!
{
myMap[toCode[i]]++;
}
map<char,int>::iterator iter;
int h=1;
for(iter=myMap.begin();iter!=myMap.end();iter++)
霍夫曼编码
四川大学计算机学院2009级戚辅光
【关键字】
霍夫曼编码原理霍夫曼译码原理霍夫曼树霍夫曼编码源代码 霍夫曼编码分析霍夫曼编码的优化霍夫曼编码的应用
【摘要】
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。它属于可变代码长度算法一族。意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
{
char ch; //字符
int s[50]; //ch的编码
intlen; //编码长度
};
intnNode; //叶子节点数目
inttotalNode; //霍夫曼树的总节点个数
char toCode[100000] ; //待编码的字符串
myNodemyToCode[100000]; //待编码的字符串和权值
cout<<"\n作者:戚辅光"<<endl;
cout<<"时间:2010-11-23"<<endl;
while(1)
{
printf("请输入待编码的字符串\n");
int flag=0;
gets(toCode);
intlen=strlen(toCode);
if(len==1)
{
flag=1;
}
Len=len;
if(fang=='N')
{
break;
}
getchar();
}
return 0;
}
void build(int n) //建立霍夫曼树
{
int i;
int m=2*n-1; //n个叶子节点的霍夫曼树总节点数为2*n-1
for(i=1;i<=n;i++) //初始化霍夫曼数组
{
myHuffmantree[i].weight=weightOfToCode[i]; //叶子节点权值为字符出现次数
int Len; //待编码的字符的总长度
int Coding[100000]; //译码之后的01串
intlenOfCoding ; //01串的长度
void build(int n); //建立霍夫曼树
void select(int&a,int&b); //选择两个权值最小的节点
void Code(); //编码
根据上面的结论,我们可以很清楚地直到译码的方法:
定义两个指针p1,p2,P1指向当前编码的开始位置,P2指向当前编码的位置,如果P1-P2这一段编码能在编码库里面找到完全对应的编码结果,则译码成功,该段编码的译码结果就是与编码库里完全对应的编码的字符。循环次操作,直到译码结束!
例一:
假设有一段字符含有a,,c,d三个字符,经过编码之后三个字符对应的编码结果分别为:
void printCode(); //打印编码
void deCode(); //译码
int match(intl,int h);
int main()
{
int i;
cout<<"\n=============================霍夫曼编码程序=============================";
sign1=i;
}
}
}
for(i=1;i<=totalNode;i++)
{
if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点
霍夫曼译码原理:
对于霍夫曼的译码,可以肯定的是其译码结果是唯一的。
证明:因为霍夫曼编码是根据霍夫曼树来确定的,霍夫曼树是一棵二叉树,编码的时候是从树根一直往下走,直到走到叶子节点为止,在其经过的路径上,如果是树的左子树则为0,否则为1。因为每一次都要走到树的叶子节点,多以不可能存在两个编码a和b,使得a是b的前缀或者b是a的前缀。所以编码一定可以唯一确定。
【正文】
引言
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
霍夫曼编码原理:
霍夫曼编码的基本思想:输入一个待编码的串,首先统计串中各字符出现的次数,称之为频次,假设统计频次的数组为count[],则霍夫曼编码每次找出count数组中的值最小的两个分别作为左右孩子,建立他们的父节点,循环这个操作2*n-1-n(n是不同的字符数)次,这样就把霍夫曼树建好了。建树的过程需要注意,首先把count数组里面的n个值初始化为霍夫曼树的n个叶子节点,他们的孩子节点的标号初始化为-1,父节点初始化为他本身的标号。接下来是编码,每次从霍夫曼树的叶子节点出发,依次向上找,假设当前的节点标号是i,那么他的父节点必然是myHuffmantree[i].parent,如果i是myHuffmantree[i].parent的左节点,则该节点的路径为0,如果是右节点,则该节点的路径为1。当向上找到一个节点,他的父节点标号就是他本身,就停止(说明该节点已经是根节点)。还有一个需要注意的地方:在查找当前权值最小的两个节点时,那些父节点不是他本身的节点不能考虑进去,因为这些节点已经被处理过了。
printCode();
cout<<"\n-------------------------01串的译码结果如下-----------------------------\n";
deCode();
cout<<"\n是否继续?(Y/N)\n";
char con[10];
cin>>con;
char fang=toupper(con[0]);
myHuffmantree[i].ld=-1; //叶子节点没有左孩子
myHuffmantree[i].rd=-1; //叶子节点没有右孩子
myHuffmantree[i].parent=i; //叶子节点父节点先初始化为他本身
}
for(i=n+1;i<=m;i++)
{
inta,b;
select(a,b);
myHuffmantree[a].parent=i;
myHuffmantree[b].parent=i;
myHuffmantree[i].ld=a;
myHuffmantree[i].rd=b;
myHuffmantree[i].weight=myHuffmantree[a].weight+myHuffmantree[b].weight;
cout<<"字符次数"<<endl;
for(i=1;i<h;i++) //显示将要编码的字符串中的各字符和他出现的次数!
{
cout<<" "<<myToCode[i].ch<<" "<<myToCode[i].num<<endl;
}
cout<<endl;
totalNode=nNode; //totalNode初始值为nNode
cout<<"-----------霍夫曼树节点信息如下(子节点为-1表示是叶子节点)---------------"<<endl<<endl;
build(nNode);
cout<<endl;
Code();
cout<<"\n-------------------------字符串的编码结果如下--------------------------\n";
else if(myHuffmantree[j].rd==x)
{
numOfCode[h++]=1;
}
}
cout<<" "<<allchar[i]<<" : ";
int x=0;
coder[i].len=h;
coder[i].ch=allchar[i];
for(int k=h-1;k>=0;k--)
a:01
c:010
d:011
现在给你一段编码0110101,要求将其译码!
按照上面介绍的方法我们可以直到:
编码的前三个字符是且仅是d的编码,所以011译码为d,依次译码可得整串的译码结果为daa
霍夫曼编码源代码:
#include<iostream>
#include<cstring>
#include<algorithm>
{
myToCode[h].ch=iter->first;
allchar[h]=iter->first;
weightOfToCode[h]=iter->second;
myToCode[h++].num=iter->second;
}
nNode=h-1; //叶子节点个数
cout<<"----------------------字符统计如下--------------------------------------"<<endl;
intweightOfToCode[100000] ; //字符串的权值!
HuffmantreemyHuffmantree[1000000]; //霍夫曼树(数组模拟)
char allchar[1000000]; //所哟出现过的字符
mycode coder[1000000]; //字符与对应的编码
myHuffmantree[i].parent=i;
}
for(i=1;i<=totalNode;i++)
{
printf("节点:%3d权值:%3d左节点:%3d右节点:%3d父节点:%3d \n",i,myHuffmantree[i].weight,myHuffmantree[i].ld,myHuffmantree[i].rd,myHuffmantree[i].parent);
}
}
void Code() //编码
{
inti,j;
intnumOfCode[100000];
cout<<"--------------------------各字符编码结果如下----------------------------"<<endl;
if(Len==1)
{
cout<<toCode[0]<<" : "<<"0\n";
霍夫曼树:
下面是字符串agdfaghdabsb的霍夫曼编码的霍夫曼树:
字符串:agdfaghdabsb
出现的字符
字符出现的次数
a
3
g
2
d
2
f
1
h
1
b
2
s
1
合计
12
由上面的霍夫曼树可知各个字符的编码如下:
a: 01
b:010
d:011
f:100
g:101
h:110
s:111
所以整个串的编码为:
011010111000110111001101010111010
int sign2=2; //次小值的下标
for(i=1;i<=totalNode;i++)
{
if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点
{
if(myHuffmantree[i].weight<min1)
{
min1=myHuffmantree[i].weight;
{
coder[i].s[x++]=numOfCode[k];
printf("%d",numOfCode[k]);
}
cout<<endl;
}
}
void select(int&a,int&b) //选择两个权值最小的节点
{Leabharlann Baidu
int i;
int min1=INF;
int min2=INF;
int sign1=1; //最小值的下标
#include<map>
using namespace std;
#define INF 0x7fffffff //无穷大
structHuffmantree //霍夫曼树的节点
{
int weight;
intparent,ld,rd;
};
structmyNode
{
charch;
intnum;
};
structmycode //字符和其对应的编码
return ;
}
for(i=1;i<=nNode;i++)
{
j=i;
int h=0;
while(myHuffmantree[j].parent!=j)
{
int x=j;
j=myHuffmantree[j].parent;
if(myHuffmantree[j].ld==x)
{
numOfCode[h++]=0;
map<char,int>myMap;
for(i=0;i<len;i++) //统计字符串中各字符出现的频次!
{
myMap[toCode[i]]++;
}
map<char,int>::iterator iter;
int h=1;
for(iter=myMap.begin();iter!=myMap.end();iter++)
霍夫曼编码
四川大学计算机学院2009级戚辅光
【关键字】
霍夫曼编码原理霍夫曼译码原理霍夫曼树霍夫曼编码源代码 霍夫曼编码分析霍夫曼编码的优化霍夫曼编码的应用
【摘要】
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。它属于可变代码长度算法一族。意思是个体符号(例如,文本文件中的字符)用一个特定长度的位序列替代。因此,在文件中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。
{
char ch; //字符
int s[50]; //ch的编码
intlen; //编码长度
};
intnNode; //叶子节点数目
inttotalNode; //霍夫曼树的总节点个数
char toCode[100000] ; //待编码的字符串
myNodemyToCode[100000]; //待编码的字符串和权值
cout<<"\n作者:戚辅光"<<endl;
cout<<"时间:2010-11-23"<<endl;
while(1)
{
printf("请输入待编码的字符串\n");
int flag=0;
gets(toCode);
intlen=strlen(toCode);
if(len==1)
{
flag=1;
}
Len=len;
if(fang=='N')
{
break;
}
getchar();
}
return 0;
}
void build(int n) //建立霍夫曼树
{
int i;
int m=2*n-1; //n个叶子节点的霍夫曼树总节点数为2*n-1
for(i=1;i<=n;i++) //初始化霍夫曼数组
{
myHuffmantree[i].weight=weightOfToCode[i]; //叶子节点权值为字符出现次数
int Len; //待编码的字符的总长度
int Coding[100000]; //译码之后的01串
intlenOfCoding ; //01串的长度
void build(int n); //建立霍夫曼树
void select(int&a,int&b); //选择两个权值最小的节点
void Code(); //编码
根据上面的结论,我们可以很清楚地直到译码的方法:
定义两个指针p1,p2,P1指向当前编码的开始位置,P2指向当前编码的位置,如果P1-P2这一段编码能在编码库里面找到完全对应的编码结果,则译码成功,该段编码的译码结果就是与编码库里完全对应的编码的字符。循环次操作,直到译码结束!
例一:
假设有一段字符含有a,,c,d三个字符,经过编码之后三个字符对应的编码结果分别为:
void printCode(); //打印编码
void deCode(); //译码
int match(intl,int h);
int main()
{
int i;
cout<<"\n=============================霍夫曼编码程序=============================";
sign1=i;
}
}
}
for(i=1;i<=totalNode;i++)
{
if(myHuffmantree[i].parent==i) //说明其是已经更新过的节点
霍夫曼译码原理:
对于霍夫曼的译码,可以肯定的是其译码结果是唯一的。
证明:因为霍夫曼编码是根据霍夫曼树来确定的,霍夫曼树是一棵二叉树,编码的时候是从树根一直往下走,直到走到叶子节点为止,在其经过的路径上,如果是树的左子树则为0,否则为1。因为每一次都要走到树的叶子节点,多以不可能存在两个编码a和b,使得a是b的前缀或者b是a的前缀。所以编码一定可以唯一确定。
【正文】
引言
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。uffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
霍夫曼编码原理:
霍夫曼编码的基本思想:输入一个待编码的串,首先统计串中各字符出现的次数,称之为频次,假设统计频次的数组为count[],则霍夫曼编码每次找出count数组中的值最小的两个分别作为左右孩子,建立他们的父节点,循环这个操作2*n-1-n(n是不同的字符数)次,这样就把霍夫曼树建好了。建树的过程需要注意,首先把count数组里面的n个值初始化为霍夫曼树的n个叶子节点,他们的孩子节点的标号初始化为-1,父节点初始化为他本身的标号。接下来是编码,每次从霍夫曼树的叶子节点出发,依次向上找,假设当前的节点标号是i,那么他的父节点必然是myHuffmantree[i].parent,如果i是myHuffmantree[i].parent的左节点,则该节点的路径为0,如果是右节点,则该节点的路径为1。当向上找到一个节点,他的父节点标号就是他本身,就停止(说明该节点已经是根节点)。还有一个需要注意的地方:在查找当前权值最小的两个节点时,那些父节点不是他本身的节点不能考虑进去,因为这些节点已经被处理过了。
printCode();
cout<<"\n-------------------------01串的译码结果如下-----------------------------\n";
deCode();
cout<<"\n是否继续?(Y/N)\n";
char con[10];
cin>>con;
char fang=toupper(con[0]);
myHuffmantree[i].ld=-1; //叶子节点没有左孩子
myHuffmantree[i].rd=-1; //叶子节点没有右孩子
myHuffmantree[i].parent=i; //叶子节点父节点先初始化为他本身
}
for(i=n+1;i<=m;i++)
{
inta,b;
select(a,b);
myHuffmantree[a].parent=i;
myHuffmantree[b].parent=i;
myHuffmantree[i].ld=a;
myHuffmantree[i].rd=b;
myHuffmantree[i].weight=myHuffmantree[a].weight+myHuffmantree[b].weight;
cout<<"字符次数"<<endl;
for(i=1;i<h;i++) //显示将要编码的字符串中的各字符和他出现的次数!
{
cout<<" "<<myToCode[i].ch<<" "<<myToCode[i].num<<endl;
}
cout<<endl;
totalNode=nNode; //totalNode初始值为nNode
cout<<"-----------霍夫曼树节点信息如下(子节点为-1表示是叶子节点)---------------"<<endl<<endl;
build(nNode);
cout<<endl;
Code();
cout<<"\n-------------------------字符串的编码结果如下--------------------------\n";