贪心算法-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,统一了字符串的个数,在输出时可能有错误 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春哥111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值