一、概述
今天这篇我们来简单介绍下贪婪算法,贪婪算法分阶段工作,在每个阶段可以认为所做决定是最好的,而不考虑将来的后果。通常这意味着选择的是某个局部最优解。这种“眼下能够拿到就拿”的策略是这类算法的名称来源。
当算法终止的时候,我们希望局部最优等于全局最优,如果这样的话,那么算法就是正确的,否则,算法得到的是一个次最优解,如果不要求绝对的最佳答案,那么有时使用简单的贪婪算法生成近似最优解反而是更好的选择。
二、贪婪算法的应用
第一个实际应用:文件压缩。
假设我们有一个文件,它只包含a,e,i,s,t,加上一些空格和换行符,如果该文件中有10个a、15个e、12个i,3个s、4个t,13个空格和1个换行符。每个字符需要占用3bit大小,上述假设的文件有58个字符,需要174(bit)。如下图所示(以下字符的编码只是举例,一个数字代表1bit)
现在我们要使用一种策略,对这些字符重新进行编码,让其尽可能的减少占用空间,该用怎样的策略呢?
首先我们要保证字符的编码是前缀码,什么是前缀码呢?说白了,前缀码不关心字符编码的长度是否一致,只需要保证没有字符编码是别的字符编码的前缀就行。接下来我们介绍一种产生最优前缀码的算法:赫夫曼编码
什么是赫夫曼编码?我用自己的理解表述一下:对于N个字符,每个字符都有它出现的频率,首先我们将所有字符当做节点,任意取两个出现频率最低的节点生成一个新树,新树的根节点权重就是两个字符出现的频率和,再将剩下的节点(包括新生成的树根节点)做同样的操作,取出两个最小权重的节点合成新树,最终经过N-1次合并,我们就可以得到一棵树,(满二叉树)这棵树就是最优的赫夫曼编码树。
为了更好的理解,接下来我用作图的方式来演示下赫夫曼树的生成过程,如下图所示为初始状态,幂位我用来表示字符出现的频率。
第一次合并后,结果如下图所示
第二次合并后如下