算法笔记贪心算法哈夫曼编码问题.docx
- 文档编号:28523691
- 上传时间:2023-07-18
- 格式:DOCX
- 页数:22
- 大小:203.58KB
算法笔记贪心算法哈夫曼编码问题.docx
《算法笔记贪心算法哈夫曼编码问题.docx》由会员分享,可在线阅读,更多相关《算法笔记贪心算法哈夫曼编码问题.docx(22页珍藏版)》请在冰豆网上搜索。
算法笔记贪心算法哈夫曼编码问题
0023算法笔记——【贪心算法】哈夫曼编码问题
1、问题描述
哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。
其压缩率通常在20%~90%之间。
哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。
一个包含100,000个字符的文件,各字符出现频率不同,如下表所示。
有多种方式表示文件中的信息,若用0,1码表示字符的方法,即每个字符用唯一的一个0,1串表示。
若采用定长编码表示,则需要3位表示一个字符,整个文件编码需要300,000位;若采用变长编码表示,给频率高的字符较短的编码;频率低的字符较长的编码,达到整体编码减少的目的,则整个文件编码需要(45×1+13×3+12×3+16×3+9×4+5×4)×1000=224,000位,由此可见,变长码比定长码方案好,总码长减小约25%。
前缀码:
对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。
这种编码称为前缀码。
编码的前缀性质可以使译码方法非常简单;例如001011101可以唯一的分解为0,0,101,1101,因而其译码为aabe。
译码过程需要方便的取出编码的前缀,因此需要表示前缀码的合适的数据结构。
为此,可以用二叉树作为前缀码的数据结构:
树叶表示给定字符;从树根到树叶的路径当作该字符的前缀码;代码中每一位的0或1分别作为指示某节点到左儿子或右儿子的“路标”。
从上图可以看出,表示最优前缀码的二叉树总是一棵完全二叉树,即树中任意节点都有2个儿子。
图a表示定长编码方案不是最优的,其编码的二叉树不是一棵完全二叉树。
在一般情况下,若C是编码字符集,表示其最优前缀码的二叉树中恰有|C|个叶子。
每个叶子对应于字符集中的一个字符,该二叉树有|C|-1个内部节点。
给定编码字符集C及频率分布f,即C中任一字符c以频率f(c)在数据文件中出现。
C的一个前缀码编码方案对应于一棵二叉树T。
字符c在树T中的深度记为dT(c)。
dT(c)也是字符c的前缀码长。
则平均码长定义为:
使平均码长达到最小的前缀码编码方案称为C的最优前缀码。
2、构造哈弗曼编码
哈夫曼提出构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼编码。
其构造步骤如下:
(1)哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。
(2)算法以|C|个叶结点开始,执行|C|-1次的“合并”运算后产生最终所要求的树T。
(3)假设编码字符集中每一字符c的频率是f(c)。
以f为键值的优先队列Q用在贪心选择时有效地确定算法当前要合并的2棵具有最小频率的树。
一旦2棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的2棵树的频率之和,并将新树插入优先队列Q。
经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。
构造过程如图所示:
具体代码实现如下:
(1)4d4.cpp,程序主文件
[cpp] viewplain copy
1.//4d4 贪心算法 哈夫曼算法
2.#include "stdafx.h"
3.#include "BinaryTree.h"
4.#include "MinHeap.h"
5.#include
6.using namespace std。
7.
8.const int N = 6。
9.
10.template
11.
12.template
13.BinaryTree
14.
15.template
16.class Huffman
17.{
18. friend BinaryTree
19. public:
20. operator Type() const
21. {
22. return weight。
23. }
24. //private:
25. BinaryTree
26. Type weight。
27.}。
28.
29.int main()
30.{
31. char c[] = {'0','a','b','c','d','e','f'}。
32. int f[] = {0,45,13,12,16,9,5}。
//下标从1开始
33. BinaryTree
34.
35. cout<<"各字符出现的对应频率分别为:
"< 36. for(int i=1。 i<=N。 i++) 37. { 38. cout< "< 39. } 40. cout< 41. 42. cout<<"生成二叉树的前序遍历结果为: "< 43. t.Pre_Order()。 44. cout< 45. 46. cout<<"生成二叉树的中序遍历结果为: "< 47. t.In_Order()。 48. cout< 49. 50. t.DestroyTree()。 51. return 0。 52.} 53. 54.template 55.BinaryTree 56.{ 57. //生成单节点树 58. Huffman 59. BinaryTree 60. 61. for(int i=1。 i<=n。 i++) 62. { 63. z.MakeTree(i,zero,zero)。 64. w[i].weight = f[i]。 65. w[i].tree = z。 66. } 67. 68. //建优先队列 69. MinHeap 70. for(int i=1。 i<=n。 i++) Q.Insert(w[i])。 71. 72. //反复合并最小频率树 73. Huffman 74. for(int i=1。 i i++) 75. { 76. x = Q.RemoveMin()。 77. y = Q.RemoveMin()。 78. z.MakeTree(0,x.tree,y.tree)。 79. x.weight += y.weight。 80. x.tree = z。 81. Q.Insert(x)。 82. } 83. 84. x = Q.RemoveMin()。 85. 86. delete[] w。 87. 88. return x.tree。 89.} (2)BinaryTree.h二叉树实现 [cpp] viewplain copy 1.#include 2.using namespace std。 3. 4.template 5.struct BTNode 6.{ 7. T data。 8. BTNode 9. 10. BTNode() 11. { 12. lChild=rChild=NULL。 13. } 14. 15. BTNode(const T &val,BTNode 16. { 17. data=val。 18. lChild=Childl。 19. rChild=Childr。 20. } 21. 22. BTNode 23. { 24. BTNode 25. 26. if(&data==NULL) 27. return NULL。 28. 29. nl=lChild->CopyTree()。 30. nr=rChild->CopyTree()。 31. 32. nn=new BTNode 33. return nn。 34. } 35.}。 36. 37. 38.template 39.class BinaryTree 40.{ 41. public: 42. BTNode 43. BinaryTree()。 44. ~BinaryTree()。 45. 46. void Pre_Order()。 47. void In_Order()。 48. void Post_Order()。 49. 50. int TreeHeight()const。 51. int TreeNodeCount()const。 52. 53. void DestroyTree()。 54. void MakeTree(T pData,BinaryTree 55. void Change(BTNode 56. 57. private: 58. void Destroy(BTNode 59. void PreOrder(BTNode 60. void InOrder(BTNode 61. void PostOrder(BTNode 62. 63. int Height(const BTNode 64. int NodeCount(const BTNode 65.}。 66. 67.template 68.BinaryTree : BinaryTree() 69.{ 70. root=NULL。 71.} 72. 73.template 74.BinaryTree : ~BinaryTree() 75.{ 76. 77.} 78. 79.template 80.void BinaryTree : Pre_Order() 81.{ 82. PreOrder(root)。 83.} 84. 85.template 86.void BinaryTree : In_Order() 87.{ 88. InOrder(root)。 89.} 90. 91.template 92.void BinaryTree : Post_Order() 93.{ 94. PostOrder(root)。 95.} 96. 97.template 98.int BinaryTree : TreeHeight()const 99.{ 100. return Height(root)。 101.} 102. 103.template 104.int BinaryTree : TreeNodeCount()const 105.{ 106. return NodeCount(root)。 107.} 108. 109.template 110.void BinaryTree : DestroyTree() 111.{ 112. Destroy(root)。 113.} 114. 115.template 116.void BinaryTree : PreOrder(BTNode 117.{ 118. if(r! =NULL) 119. { 120. cout< 121. PreOrder(r->lChild)。 122. PreOrder(r->rChild)。 123. } 124.} 125. 126.template 127.void BinaryTree : InOrder(BTNode 128.{ 129. if(r! =NULL) 130. { 131. InOrder(r->lChild)。 132. cout< 133. InOrder(r->rChild)。 134. } 135.} 136. 137.template 138.void BinaryTree : PostOrder(BTNode 139.{ 140. if(r! =NULL) 141. { 142. PostOrder(r->lChild)。 143. PostOrder(r->rChild)。 144. cout< 145. } 146.} 147. 148.template 149.int BinaryTree : NodeCount(const BTNode 150.{ 151. if(r==NULL) 152. return 0。 153. else 154. return 1+NodeCount(r->lChild)+NodeCount(r->rChild)。 155.} 156. 157.template 158.int BinaryTree : Height(const BTNode 159.{ 160. if(r==NULL) 161. return 0。 162. else 163. { 164. int lh,rh。 165. lh=Height(r->lChild)。 166. rh=Height(r->rChild)。 167. return 1+(lh>rh? lh: rh)。 168. } 169.} 170. 171.template 172.void BinaryTree : Destroy(BTNode 173.{ 174. if(r! =NULL) 175. { 176. Destroy(r->lChild)。 177. Destroy(r->rChild)。 178. delete r。 179. r=NULL。 180. } 181.} 182. 183.template 184.void BinaryTree : Change(BTNode 185.{ 186. BTNode 187. if(r){ 188. p=r->lChild。 189. r->lChild=r->rChild。 190. r->rChild=p。 //左右子女交换 191. Change(r->lChild)。 //交换左子树上所有结点的左右子树 192. Change(r->rChild)。 //交换右子树上所有结点的左右子树 193. } 194.} 195. 196.template 197.void BinaryTree : MakeTree(T pData,BinaryTree 198.{ 199. root = new BTNode 200. root->data = pData。 201. root->lChild = leftTree.root。 202. root->rChild = rightTree.root。 203.} (3)MinHeap.h最小堆实现 [cpp] viewplain copy 1.#include 2.using namespace std。 3.template 4.class MinHeap 5.{ 6. private: 7. T *heap。 //元素数组,0号位置也储存元素 8. int CurrentSize。 //目前元素个数 9. int MaxSize。 //可容纳的最多元素个数 10. 11. void FilterDown(const int start,const int end)。 //自上往下调整,使关键字小的节点在上 12. void FilterUp(int start)。 //自下往上调整 13. 14. public: 15. MinHeap(int n=1000)。 16. ~MinHeap()。 17. bool Insert(const T &x)。 //插入元素 18. 19. T RemoveMin()。 //删除最小元素 20. T GetMin()。 //取最小元素 21. 22. bool IsEmpty() const。 23. bool IsFull() const。 24. void Clear()。 25.}。 26. 27.template 28.MinHeap : MinHeap(int n) 29.{ 30. MaxSize=n。 31. heap=new T[MaxSize]。 32. CurrentSize=0。 33.} 34. 35.template 36.MinHeap : ~MinHeap() 37.{ 38. delete []heap。 39.} 40. 41.template 42.void MinHeap : FilterUp(int start) //自下往上调整 43.{ 44. int j=start,i=(j-1)/2。 //i指向j的双亲节点 45. T temp=heap[j]。 46. 47. while(j>0) 48. { 49. if(heap[i]<=temp) 50. break。 51. else 52. { 53.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 笔记 贪心 哈夫曼 编码 问题