当前位置:   article > 正文

贪心算法-赫夫曼编码_贪心算法霍夫曼编码

贪心算法霍夫曼编码

      赫夫曼编码主要用于数据文件的压缩,用满二叉树实现的,字符都位于树叶上。赫夫曼算法:在输入的字符结点中,选择出现频率最小的2个结点,合并两个结点,形成新的树。新树频率为2个结点的频率之和。在新结点和原始结点(除去合并的2个结点)再寻找出现频率最小的个结点合并。依次下去,直到所有结点都合并在一个树上,此时生成的树为赫夫曼编码树。

a(10)  e(15)    i(12)    s(3)     t(4)      p(13)     n(1)   (待编码的字符信息,后面括号中是该字符出现的频率)

n(1)    s(3)      t(4)      a(10)    i(12)    p(13)    e(15)    (程序中的insert,将其插入到list中,按出现的频率由小到大排序)

n(1)   s(3),    t(4)     T1(4)    a(10)   i(12)     p(13)     e(15) (选取出现频率最小的2个结点n、s合并成新树T1,将T1按出现频率大小插入到list中,T1的左儿子为n,右儿子s)

n(1)    s(3),     t(4)     T1(4),    T2(8)   a(10)     i(12)     p(13)     e(15)    (选取出现频率最小从t开始,T2左儿子为t,右儿子为T1)

n(1)    s(3),     t(4)     T1(4),    T2(8)   a(10),     i(12)     p(13)     e(15)    T3(18)   (选取出现频率最小从T2开始,T3左儿子T2,右儿子a)

n(1)    s(3),     t(4)     T1(4),    T2(8)   a(10),     i(12)     p(13),     e(15)    T3(18)     T4(25)     (选取出现频率最小从i开始,T4左儿子i,右儿子p)

n(1)    s(3),     t(4)     T1(4),    T2(8)   a(10),     i(12)     p(13),     e(15)    T3(18),     T4(25)   T5(33)  (选取出现频率最小从e开始,T5左儿子e,右儿子T3)

n(1)    s(3),     t(4)     T1(4),    T2(8)   a(10),     i(12)     p(13),     e(15)    T3(18),     T4(25)   T5(33),    T6(58)   (选取出现频率最小从T4开始,T6左儿子T4,右儿子T5) 

完成赫夫曼树的生成,如下图:

                                                                   

编码采用向左为0 ,向右为1,各字符对应的赫夫曼编码如下:

                          a:111  ;e:10  ;i:00   ;s:11011   ;t:1100  ;p:01   ;n:11010  。

对于程序中的code()函数如何实现记录赫夫曼码,如n的赫夫曼码获得过程:在生成赫夫曼时,n是T5的后代,而T5是根节点T6的右儿子,根据编规则向右为1,所以T5所有后代(e,t,n,s)的赫夫曼码push  1,因为T5在list中位置为k=11。在编程中判断k奇数,则该处结点的所有后代赫夫曼码push  1,T3、T2、T1对n的赫夫曼码分别是1 ,0,1。所以n赫夫曼码为11010。其实树中所有向右的结点在list中的位置为奇数,向左为偶数。在程序中判断该结点在list 中的位置,决定对其儿子赫夫曼码贡献是0还是1

代码如下:

Huuffman.h

  1. #pragma once
  2. #include<iostream>
  3. #include<list>
  4. #include<vector>
  5. using namespace std;
  6. template<typename Comparable>
  7. struct HuffNode
  8. {
  9. HuffNode *left;
  10. HuffNode *right;
  11. int num;//出现的频率
  12. Comparable name;//编码的字符串
  13. vector<int>cod;//该字符的编码
  14. HuffNode(Comparable n,int nu,HuffNode *l,HuffNode *r):name(n),num(nu),left(l),right(r){}
  15. HuffNode(int nu,HuffNode *l,HuffNode *r):num(nu),left(l),right(r){}
  16. HuffNode(HuffNode *l,HuffNode *r):left(l),right(r){}
  17. };
  18. template<typename Comparable>
  19. class Huffmancode
  20. {
  21. public:
  22. void insert(Comparable name,int num);//将输入的字符插入vector中
  23. void huffcode();//进行赫夫曼编码
  24. void code(HuffNode<Comparable> *&t,int k);
  25. void findcode(Comparable x);//查找某元素的赫夫曼码
  26. void find(string c);//已知赫夫曼码查找其对应的元素
  27. private:
  28. list<HuffNode<Comparable> >m_huffman;//保存总的要编码的字符
  29. void findc(HuffNode<Comparable> *t,Comparable x);//查找某元素的赫夫曼码
  30. void findx(HuffNode<Comparable> *t,vector<int>co);
  31. };

Huuffman.cpp

  1. #include "stdafx.h"
  2. #include"Huffman.h"
  3. #include<iostream>
  4. #include<list>
  5. #include<vector>
  6. using namespace std;
  7. template<typename Comparable>
  8. void Huffmancode<Comparable>::insert(Comparable name,int num)
  9. {
  10. HuffNode<Comparable> huffnode(name,num,NULL,NULL);
  11. list<HuffNode<Comparable> >::iterator it;
  12. if(m_huffman.size()==0)
  13. {
  14. m_huffman.push_back(huffnode);
  15. }
  16. else
  17. {
  18. for(it=m_huffman.begin();it!=m_huffman.end();++it)//将待编码的按照出现频率的大小排序,存储在list中
  19. {
  20. if(it->num>huffnode.num)
  21. break;
  22. }
  23. m_huffman.insert(it,huffnode);
  24. }
  25. }
  26. template<typename Comparable>
  27. void Huffmancode<Comparable>::huffcode()//生成赫夫曼树
  28. {
  29. int k=0;
  30. list<HuffNode<Comparable> >::iterator it;
  31. list<HuffNode<Comparable> >::iterator t=m_huffman.begin();
  32. list<HuffNode<Comparable> >::iterator t2=++t;
  33. list<HuffNode<Comparable> >::iterator t1=m_huffman.begin();
  34. while(m_huffman.size()-k>1)
  35. {
  36. HuffNode<Comparable> huffnode(t1->num+t2->num,&(*t1),&(*t2));
  37. HuffNode<Comparable>* m1=&(*t1);
  38. HuffNode<Comparable>* m2=&(*t2);
  39. code(m1,k); //进行编码
  40. code(m2,k+1); //进行编码
  41. k=k+2;
  42. for(it=m_huffman.begin();it!=m_huffman.end();++it)
  43. {
  44. if(it->num>huffnode.num)
  45. {
  46. break;
  47. }
  48. }
  49. m_huffman.insert(it,huffnode);
  50. ++(++t1);
  51. ++(++t2);
  52. }
  53. }
  54. template<typename Comparable>
  55. void Huffmancode<Comparable>::code(HuffNode<Comparable> *&t,int k)//编码
  56. {
  57. if(k%2==0)
  58. {
  59. if(t!=NULL)
  60. {
  61. t->cod.push_back(0);
  62. code(t->left,k);
  63. code(t->right,k);
  64. }
  65. }
  66. else
  67. {
  68. if(t!=NULL)
  69. {
  70. t->cod.push_back(1);
  71. code(t->left,k);
  72. code(t->right,k);
  73. }
  74. }
  75. }
  76. //查找某个元素的编码
  77. template<typename Comparable>
  78. void Huffmancode<Comparable>::findcode(Comparable x)
  79. {
  80. list<HuffNode<Comparable> >::iterator it=m_huffman.end();
  81. --it;
  82. HuffNode<Comparable> *t=&(*it); //获取赫夫曼树的根节点的地址,由前面huffcode()函数生成赫夫曼树可知,根节点是存储在list中的最后一个位置
  83. findc(t,x);
  84. cout<<endl;
  85. }
  86. template<typename Comparable>
  87. void Huffmancode<Comparable>::findc(HuffNode<Comparable> *t,Comparable x)
  88. {
  89. if(t!=NULL)
  90. {
  91. if(t->name==x) //采用遍历树的方法,直到找到name为x的结点,然后把其编码输出
  92. {
  93. for(int i=t->cod.size()-1;i>=0;i--)
  94. cout<<t->cod[i]<<" ";
  95. }
  96. findc(t->left,x);
  97. findc(t->right,x);
  98. }
  99. }
  100. //解码,已知某个赫夫曼码找到对应的元素
  101. template<typename Comparable>
  102. void Huffmancode<Comparable>::find(string c)
  103. {
  104. list<HuffNode<Comparable> >::iterator it=m_huffman.end();
  105. --it;
  106. HuffNode<Comparable> *t=&(*it); //获取赫夫曼树的根节点
  107. vector<int>co;
  108. int temp;
  109. for(int i=c.size()-1;i>=0;i--)//将输入的string类型每一位上转换为int并放在vector中
  110. {
  111. temp=(int)c[i]-48; //1是char类型时,转换为int类型,值为49,需要减48
  112. co.push_back(temp);
  113. }
  114. findx(t,co); //co中保存的是赫夫曼码
  115. cout<<endl;
  116. }
  117. template<typename Comparable>
  118. void Huffmancode<Comparable>::findx(HuffNode<Comparable> *t,vector<int>co)
  119. {
  120. if(t!=NULL)
  121. {
  122. if(t->cod==co) //遍历赫夫曼树,找到赫夫曼码为co的结点,输出对应的元素,完成解码工作
  123. cout<<"name:"<<t->name<<endl;
  124. findx(t->left,co);
  125. findx(t->right,co);
  126. }
  127. }


Algorithm-greedy2.cpp

  1. // Algorithm-greedy2.cpp : 定义控制台应用程序的入口点。
  2. //
  3. //主要实现赫夫曼编码
  4. #include "stdafx.h"
  5. #include"Huffman.h"
  6. #include"Huffman.cpp"
  7. #include<iostream>
  8. #include<string>
  9. #include<list>
  10. #include<vector>
  11. using namespace std;
  12. int _tmain(int argc, _TCHAR* argv[])
  13. {
  14. Huffmancode<string> c;
  15. c.insert("a",10);
  16. c.insert("e",15);
  17. c.insert("i",12);;
  18. c.insert("s",3);
  19. c.insert("t",4);
  20. c.insert("p",13);
  21. c.insert("n",1);
  22. c.huffcode();
  23. c.findcode("a");//查找字符为a的赫夫曼码
  24. c.find("11010");//查找赫夫曼码对应的字符
  25. return 0;
  26. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/693617
推荐阅读
相关标签
  

闽ICP备14008679号