贪心算法-Huffman算法

哈夫曼编码是一种编码方式,属于可变字长编码(VLC)的一种,该编码方式是数学家D.A.Huffman于1952年提出的,是用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式,称之为最佳编码
哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方式,其压缩率通常在20%~90%之间,JPEG就是用哈夫曼编码压缩的
任何一个字符的编码都不能使其他字符编码的前缀,否则译码时将产生二义性 

 哈夫曼算法的构造思想及设计

1.构造思想
将所要编码的字符作为叶子节点,在文件中使用频率作为叶子节点的权值,以自底向上的方式、通过n-1次的"合并"运算后构造出最终所要求的树
核心思想:让权值大的叶子离根最近

哈夫曼树中节点的存储结构

n个叶子节点的哈夫曼树共有2n-1个节点,并且需要进行n-1次合并操作。为了便于选取根节点权值最小的二叉树以及进行合并操作,树种每个节点的存储结构为:
struct HtNode{
double weight;
int parent,lchild,rchild;
};
其中,weight域表示节点的权值,即为该字符的使用频率,parent域表示节点的双亲节点在数组中的下标;lchild域表示节点的左孩子在数组中的下标;rchild域表示节点的右孩子在数组中的下标
哈夫曼树的存储结构
struct HtTree{
struct HtNode ht[MaxNode];
int root;
};
typedef struct HtTree* PHtTree;

 

 线性结构上实现的Haffman算法

//构造具有n个节点的哈夫曼树
PHtTree Huffman (int n,double w[n])//构造具有n个节点的哈夫曼树
{
PHtTree pht;
//p1,p2用于记录权值最小的两棵树在数组中的位置
int i,j,p1,p2;
//min1,min2用于记录两个最小的权值
double min1,min2;
if(n<=1) return;
//动态分配Haffman树的空间
pht=(PHtTree)malloc(sizeof(struct HtTree));
pht->ht=(struct HtNode*)malloc (sizeof(struct HtMode)*(2*n-1));
//初始化,设置ht数组的初始值
for(i=0;i<2*n-1;i++)
{
pht->ht[i].parent=0;
if(i<n)
{
pht->ht[i].weight=w[i];
}
else
{
pht->ht[i].weight=-1;
}
}
//执行n-1次合并操作,即构造哈夫曼树的n-1个内部节点
for(i=0;i<n-1;i++)
{
p1=p2=0;
//相关变量赋初值
min1=min2=∞;
for(j=0;j<n+i;j++)
{
if(pht->ht[j].parent==0)
{
if(pht->ht[j].weight<min1)
{
min2=min1;
min1=pht->ht[j].weight;
p2=p1;
p1=j;
}
else if(pht->ht[j].weight<min2)
{
min2=pht->ht[j].weight;
p2=j;
}
}
pht->ht[p1].parent=n+i;
pht->ht[p2].parent=n+i;
pht->ht[n+i].weight=min1+min2;
pht->ht[n+i].lchild=p1;
pht->ht[n+i].rchild=p2;
}
return pht;
}
//哈夫曼编码算法描述
注:从叶子到根逆向求每个字符的哈夫曼编码算法
void HuffmanCode(char** HC,int n,PHtTree pht)
{
//每个字符的编码最大长度不会超过n
char c[n];
//分配n个字符指针数组的空间
HC=(char**)malloc(n*sizeof(char*));
//第n-1单元存储编码串的结束符
c[n-1]="\0";
//逐个对n个字符求其哈夫曼编码
for(i=1;i<=n;i++)
{
start=n-1;
//k,f是两个工作指针,f指向k的父亲
for(int k=i,f=pht->ht[i].parent;f!=0;k=f,f=pht->ht[k].parent)
{
//左边分配0,右边分配1
if(pht->ht[f].lchild==k)
{
c[--start]="0";
}
else
{
c[--start]="1";
}
}
//为第i个字符编码分配空间
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&c[start]);
}
}

 其中在选择最小和次小节点时,该代码有错误

 编码使用start,统一了字符串的个数,在输出时可能有错误 

posted @ 2012-10-01 14:12  zhouqian7890  阅读(1345)  评论(0编辑  收藏  举报