赫夫曼树与赫夫曼编码
2011-03-22 13:01
204 查看
【问题描述】
利用Huffman编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接受端将传来的数据编码进行译码(复原)。对于有些信道,每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个Huffman的编/译码系统。给定一组权值{7,9,5,6,10,1,13,15,4,8},构造一棵赫夫曼树,并计算带权路径长度WPL。
【数据描述】
//- - - - - 赫夫曼树的存储表示 - - - - -
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode; //用顺序存储结构表示赫夫曼树的结点结构定义
//动态分配数组存储Huffman编码表
【算法描述】
1.初始化:从键盘读入n个字符,以及它们的权值,建立Huffman树
2.编码:根据建立的Huffman树,求每个字符的Huffman编码。对给定的待编码字符序列进行编码。
3.译码:利用已经建立好的Huffman树,对上面的编码结果译码。译码的过程是分解电文中的字符串,从根结点出发,按字符’0’和’1’确定找左孩子或右孩子,直至叶结点,便求得该子串相应的字符。
4.打印 Huffman树。
【C源程序】
/*实现初始化,建立Huffman树,并完成字符的编码*/
#include <stdio.h>
#define N 10 /*待编码字符的个数,即树中叶结点的最大个数*/
#define M 2*N-1 /*树中总的结点数目*/
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode; /*树中结点的结构*/
typedef struct {
char data; /*待编码的字符*/
int weight; /*字符的权值 */
char code
; /*字符的编码 */
} HTCode;
void Init(HTCode hc[],int *n){
/*初始化,读入待编码字符的个数n,从键盘输入n个字符和n个权值*/
int i;
printf("/ninput n=");
scanf("%d",&(*n));
printf("/ninput %d character/n",*n);
for (i=1;i<=*n;i++) hc[i].data=getch();
printf("/ninput %d weight/n",*n);
for (i=1;i<=*n;i++) scanf("%d",&(hc[i].weight));
}
void Select(HTNode ht[],int k,int *s1,int *s2){
/*ht[1…k]中选择parent为0,并且weight最小的两个结点
其序号由指针变量s1,s2指向*/
int i;
for (i=1;i<=k && ht[i].parent!=0 ;i++);
*s1=i;
for (i=1;i<=k;i++)
if (ht[i].parent==0 && ht[i].weight<ht[*s1].weight) *s1=i;
for (i=1; i<=k ; i++)
if (ht[i].parent==0 && i!=*s1) break;
*s2=i;
for (i=1;i<=k;i++)
if ( ht[i].parent==0 && i!=*s1 && ht[i].weight<ht[*s2].weight) *s2=i;
}
void HuffmanCoding(HTNode ht[],HTCode hc[],int n){
/*构造Huffman树ht,并求出n个字符的编码*/
char cd
;
int i,j,m,c,f,s1,s2,start;
m=2*n-1;
for (i=1;i<=m;i++){
if (i<=n) ht[i].weight=hc[i].weight;
else ht[i].weight=0;
ht[i].parent=ht[i].lchild=ht[i].rchild=0;
}
for (i=n+1;i<=m;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;
}
cd[n-1]='/0';
for (i=1;i<=n;i++) {
start=n-1;
for (c=i,f=ht[i].parent;f;c=f,f=ht[f].parent)
if (ht[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
strcpy(hc[i].code,&cd[start]);
}
}
main(){
int i,m,n,w[N+1];
HTNode ht[M+1];
HTCode hc[N+1];
Init(hc,&n); /*初始化*/
HuffmanCoding(ht,hc,n);/*构造Huffman树,并形成字符的编码*/
/*输出字符的编码*/
for (i=1;i<=n;i++)printf("/n%c --- %s",hc[i].data,hc[i].code);
}
【测试数据】
1. 根据运行提示,依次输入待编码的字符个数和这些字符,以及每个字符的权值:
input n=4↙
input 4character
abcd↙
input4 weight
7 5 2 4↙
输出:
a --- 0
b --- 10
c --- 110
d --- 111
2.可根据运行提示,自行指定数据,观察程序的运行结果。
【说明】
此处只是Huffman树的建立和编码算法的实现,一个完整的Huffman编/译码系统应进一步完善,实现以上算法描述的四个基本要求,并可考虑将Hufmman树和Huffman编码存在磁盘文件中。
利用Huffman编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接受端将传来的数据编码进行译码(复原)。对于有些信道,每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个Huffman的编/译码系统。给定一组权值{7,9,5,6,10,1,13,15,4,8},构造一棵赫夫曼树,并计算带权路径长度WPL。
【数据描述】
//- - - - - 赫夫曼树的存储表示 - - - - -
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode; //用顺序存储结构表示赫夫曼树的结点结构定义
//动态分配数组存储Huffman编码表
【算法描述】
1.初始化:从键盘读入n个字符,以及它们的权值,建立Huffman树
2.编码:根据建立的Huffman树,求每个字符的Huffman编码。对给定的待编码字符序列进行编码。
3.译码:利用已经建立好的Huffman树,对上面的编码结果译码。译码的过程是分解电文中的字符串,从根结点出发,按字符’0’和’1’确定找左孩子或右孩子,直至叶结点,便求得该子串相应的字符。
4.打印 Huffman树。
【C源程序】
/*实现初始化,建立Huffman树,并完成字符的编码*/
#include <stdio.h>
#define N 10 /*待编码字符的个数,即树中叶结点的最大个数*/
#define M 2*N-1 /*树中总的结点数目*/
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode; /*树中结点的结构*/
typedef struct {
char data; /*待编码的字符*/
int weight; /*字符的权值 */
char code
; /*字符的编码 */
} HTCode;
void Init(HTCode hc[],int *n){
/*初始化,读入待编码字符的个数n,从键盘输入n个字符和n个权值*/
int i;
printf("/ninput n=");
scanf("%d",&(*n));
printf("/ninput %d character/n",*n);
for (i=1;i<=*n;i++) hc[i].data=getch();
printf("/ninput %d weight/n",*n);
for (i=1;i<=*n;i++) scanf("%d",&(hc[i].weight));
}
void Select(HTNode ht[],int k,int *s1,int *s2){
/*ht[1…k]中选择parent为0,并且weight最小的两个结点
其序号由指针变量s1,s2指向*/
int i;
for (i=1;i<=k && ht[i].parent!=0 ;i++);
*s1=i;
for (i=1;i<=k;i++)
if (ht[i].parent==0 && ht[i].weight<ht[*s1].weight) *s1=i;
for (i=1; i<=k ; i++)
if (ht[i].parent==0 && i!=*s1) break;
*s2=i;
for (i=1;i<=k;i++)
if ( ht[i].parent==0 && i!=*s1 && ht[i].weight<ht[*s2].weight) *s2=i;
}
void HuffmanCoding(HTNode ht[],HTCode hc[],int n){
/*构造Huffman树ht,并求出n个字符的编码*/
char cd
;
int i,j,m,c,f,s1,s2,start;
m=2*n-1;
for (i=1;i<=m;i++){
if (i<=n) ht[i].weight=hc[i].weight;
else ht[i].weight=0;
ht[i].parent=ht[i].lchild=ht[i].rchild=0;
}
for (i=n+1;i<=m;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;
}
cd[n-1]='/0';
for (i=1;i<=n;i++) {
start=n-1;
for (c=i,f=ht[i].parent;f;c=f,f=ht[f].parent)
if (ht[f].lchild==c) cd[--start]='0';
else cd[--start]='1';
strcpy(hc[i].code,&cd[start]);
}
}
main(){
int i,m,n,w[N+1];
HTNode ht[M+1];
HTCode hc[N+1];
Init(hc,&n); /*初始化*/
HuffmanCoding(ht,hc,n);/*构造Huffman树,并形成字符的编码*/
/*输出字符的编码*/
for (i=1;i<=n;i++)printf("/n%c --- %s",hc[i].data,hc[i].code);
}
【测试数据】
1. 根据运行提示,依次输入待编码的字符个数和这些字符,以及每个字符的权值:
input n=4↙
input 4character
abcd↙
input4 weight
7 5 2 4↙
输出:
a --- 0
b --- 10
c --- 110
d --- 111
2.可根据运行提示,自行指定数据,观察程序的运行结果。
【说明】
此处只是Huffman树的建立和编码算法的实现,一个完整的Huffman编/译码系统应进一步完善,实现以上算法描述的四个基本要求,并可考虑将Hufmman树和Huffman编码存在磁盘文件中。
相关文章推荐