赞
踩
赫夫曼编码主要用于数据文件的压缩,用满二叉树实现的,字符都位于树叶上。赫夫曼算法:在输入的字符结点中,选择出现频率最小的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
- #pragma once
- #include<iostream>
- #include<list>
- #include<vector>
- using namespace std;
- template<typename Comparable>
- struct HuffNode
- {
- HuffNode *left;
- HuffNode *right;
- int num;//出现的频率
- Comparable name;//编码的字符串
- vector<int>cod;//该字符的编码
- HuffNode(Comparable n,int nu,HuffNode *l,HuffNode *r):name(n),num(nu),left(l),right(r){}
- HuffNode(int nu,HuffNode *l,HuffNode *r):num(nu),left(l),right(r){}
- HuffNode(HuffNode *l,HuffNode *r):left(l),right(r){}
- };
- template<typename Comparable>
- class Huffmancode
- {
- public:
- void insert(Comparable name,int num);//将输入的字符插入vector中
- void huffcode();//进行赫夫曼编码
- void code(HuffNode<Comparable> *&t,int k);
- void findcode(Comparable x);//查找某元素的赫夫曼码
- void find(string c);//已知赫夫曼码查找其对应的元素
- private:
- list<HuffNode<Comparable> >m_huffman;//保存总的要编码的字符
- void findc(HuffNode<Comparable> *t,Comparable x);//查找某元素的赫夫曼码
- void findx(HuffNode<Comparable> *t,vector<int>co);
- };
Huuffman.cpp
- #include "stdafx.h"
- #include"Huffman.h"
- #include<iostream>
- #include<list>
- #include<vector>
- using namespace std;
- template<typename Comparable>
- void Huffmancode<Comparable>::insert(Comparable name,int num)
- {
- HuffNode<Comparable> huffnode(name,num,NULL,NULL);
- list<HuffNode<Comparable> >::iterator it;
- if(m_huffman.size()==0)
- {
- m_huffman.push_back(huffnode);
- }
- else
- {
- for(it=m_huffman.begin();it!=m_huffman.end();++it)//将待编码的按照出现频率的大小排序,存储在list中
- {
- if(it->num>huffnode.num)
- break;
- }
- m_huffman.insert(it,huffnode);
- }
- }
- template<typename Comparable>
- void Huffmancode<Comparable>::huffcode()//生成赫夫曼树
- {
- int k=0;
- list<HuffNode<Comparable> >::iterator it;
- list<HuffNode<Comparable> >::iterator t=m_huffman.begin();
- list<HuffNode<Comparable> >::iterator t2=++t;
- list<HuffNode<Comparable> >::iterator t1=m_huffman.begin();
- while(m_huffman.size()-k>1)
- {
-
- HuffNode<Comparable> huffnode(t1->num+t2->num,&(*t1),&(*t2));
- HuffNode<Comparable>* m1=&(*t1);
- HuffNode<Comparable>* m2=&(*t2);
- code(m1,k); //进行编码
- code(m2,k+1); //进行编码
- k=k+2;
- for(it=m_huffman.begin();it!=m_huffman.end();++it)
- {
- if(it->num>huffnode.num)
- {
- break;
- }
- }
- m_huffman.insert(it,huffnode);
- ++(++t1);
- ++(++t2);
- }
- }
-
- template<typename Comparable>
- void Huffmancode<Comparable>::code(HuffNode<Comparable> *&t,int k)//编码
- {
- if(k%2==0)
- {
- if(t!=NULL)
- {
- t->cod.push_back(0);
- code(t->left,k);
- code(t->right,k);
- }
- }
- else
- {
- if(t!=NULL)
- {
- t->cod.push_back(1);
- code(t->left,k);
- code(t->right,k);
- }
- }
- }
- //查找某个元素的编码
- template<typename Comparable>
- void Huffmancode<Comparable>::findcode(Comparable x)
- {
- list<HuffNode<Comparable> >::iterator it=m_huffman.end();
- --it;
- HuffNode<Comparable> *t=&(*it); //获取赫夫曼树的根节点的地址,由前面huffcode()函数生成赫夫曼树可知,根节点是存储在list中的最后一个位置
- findc(t,x);
- cout<<endl;
- }
- template<typename Comparable>
- void Huffmancode<Comparable>::findc(HuffNode<Comparable> *t,Comparable x)
- {
- if(t!=NULL)
- {
- if(t->name==x) //采用遍历树的方法,直到找到name为x的结点,然后把其编码输出
- {
- for(int i=t->cod.size()-1;i>=0;i--)
- cout<<t->cod[i]<<" ";
- }
- findc(t->left,x);
- findc(t->right,x);
- }
- }
- //解码,已知某个赫夫曼码找到对应的元素
- template<typename Comparable>
- void Huffmancode<Comparable>::find(string c)
- {
- list<HuffNode<Comparable> >::iterator it=m_huffman.end();
- --it;
- HuffNode<Comparable> *t=&(*it); //获取赫夫曼树的根节点
- vector<int>co;
- int temp;
- for(int i=c.size()-1;i>=0;i--)//将输入的string类型每一位上转换为int并放在vector中
- {
- temp=(int)c[i]-48; //1是char类型时,转换为int类型,值为49,需要减48
- co.push_back(temp);
- }
- findx(t,co); //co中保存的是赫夫曼码
- cout<<endl;
- }
- template<typename Comparable>
- void Huffmancode<Comparable>::findx(HuffNode<Comparable> *t,vector<int>co)
- {
- if(t!=NULL)
- {
- if(t->cod==co) //遍历赫夫曼树,找到赫夫曼码为co的结点,输出对应的元素,完成解码工作
- cout<<"name:"<<t->name<<endl;
- findx(t->left,co);
- findx(t->right,co);
- }
- }
Algorithm-greedy2.cpp
- // Algorithm-greedy2.cpp : 定义控制台应用程序的入口点。
- //
- //主要实现赫夫曼编码
- #include "stdafx.h"
- #include"Huffman.h"
- #include"Huffman.cpp"
- #include<iostream>
- #include<string>
- #include<list>
- #include<vector>
- using namespace std;
- int _tmain(int argc, _TCHAR* argv[])
- {
- Huffmancode<string> c;
- c.insert("a",10);
- c.insert("e",15);
- c.insert("i",12);;
- c.insert("s",3);
- c.insert("t",4);
- c.insert("p",13);
- c.insert("n",1);
- c.huffcode();
- c.findcode("a");//查找字符为a的赫夫曼码
- c.find("11010");//查找赫夫曼码对应的字符
- return 0;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。