哈夫曼树
- 引言
最近有点傻了,回顾贪心和DP,见了问题就想用这两个思路去解题,结果无功而返。这就是所谓的人的惰性么,模仿反而死的更快,马云老师总结的不错。我现在已经本末倒置了。有时候我觉得我们真的应该想想我们做事是为了什么,活着是为了什么。本人的所有博客如有错误,或者大神有不同见解,欢迎留言,谢谢大神们的浏览与审阅。
- 题目
选自算法圣经
在保证了压缩技术后,我们怎么可以减少关键字的查询消耗呢?为什么这么说呢,看如下,分别建树如下,查询关键字会有什么后果呢?
对于所有关键字平均查找长度来说,(a)树关键字查询时间消耗比(b)树高。
- 思路
利用哈夫曼树存储数据,利用贪心法建立哈夫曼树。算法:(1)每次从这组数据(一组关键字的查询频率)中找出两个最小的查询频率;(2)在数据中删去这两个数据,并把他们的频率和插入数据当中;(3)在哈夫曼树中,第一步选出的两个数据的和就是这两个数据的根;(4)重复(1~3)步,直至这组数据的规模最终减小至1;举个例子吧:实验数据如下, 我用的关键字是英文字母,后面的数字是查询频率;
看到这相信大家都已经知道这棵哈夫曼树是什么样子的了,ok,延时到此结束。
- 实验
看个例子吧,顺便理解思路,也可以检测我的代码的正确性;实验中,我用的关键字是英文字母,后面的数字是查询频率,文本信息如下;data.txt(文件名)实验代码测试结果如下;f 5 e 9 c 12 b 13 d 16 a 45
- 代码
test.cpp(代码很水,很久以前写的,仅供参考)#include <fstream> #include <iostream> #include <string> #include <list> #include <queue> using namespace std; int const size = 6 ; // class: node for huaffman tree ; class node { public: int value ; char key ; node * leftchild ; node * rightchild ; node * parent ; node(int v,char k) ; ~node(void) ; }; node::node(int v,char k) { this -> value = v ; this -> key = k ; this -> leftchild = NULL ; this -> parent = NULL ; this -> rightchild = NULL ; } node::~node(void) { } class huaffman { list< node* > * C ; node * root ; public: huaffman( void ) ; void C_Set( ) ; void HUFFMAN( ) ; void PreorderTraver( node * p ) ; void Main( ) ; ~huaffman( void ) ; }; huaffman::huaffman( void ) { C = new list<node*> ; } void huaffman::C_Set( ) { ifstream fileReader; fileReader.open("data.txt"); int value ; char key ; node * p ; int i = 0 ; while( i < size ) { fileReader>>key>>value ; p = new node(value,key) ; C->push_front( p ) ; i++ ; } fileReader.close( ) ; } void huaffman::HUFFMAN( ) { int n = C -> size( ); node * z ,* x ,* y ; list< node * > * Q = new list< node * > ; Q ->assign( C->begin() , C->end() ) ; list <node*>::iterator Iter,min ; for( int i = 1; i<n ;i++ ) { Q->sort() ; cout<<"-------------------------------"<<endl; for ( Iter = Q->begin( ); Iter != Q->end( ); Iter++ ) { cout<<(*Iter)->key<<'\t'<<(*Iter)->value<<endl; } min = Q->begin( ); for ( Iter = Q->begin( ); Iter != Q->end( ); Iter++ ) { if( (*min)->value >(*Iter)->value ) min = Iter; } x = (*min); Q->remove( *min ); //y = Q->front(); //Q->pop_front(); min =Q->begin( ); for ( Iter = Q->begin( ); Iter != Q->end( ); Iter++ ) { if(( *min )->value>( *Iter )->value ) min = Iter; } y = ( * min ) ; Q->remove( * min ) ; z = new node(x->value+y->value,' ') ; z->leftchild = x ; z->rightchild = y ; Q->push_front(z) ; } Q->sort() ; this->root = Q->front() ; } void huaffman::PreorderTraver( node * p ) { if( p ) { cout<< p->key<<" \t "<<p->value<<endl ; this->PreorderTraver(p->leftchild) ; this->PreorderTraver(p->rightchild) ; } } void huaffman::Main( ) { this -> C_Set( ) ; this -> HUFFMAN() ; cout<<endl<<"tree follows"<<endl ; this->PreorderTraver(this->root) ; } huaffman::~huaffman( void ) { C->clear(); } int main() { huaffman * H = new huaffman(); H->Main(); delete H; system("pause"); return 0; }