哈夫曼树
最近有点傻了,回顾贪心和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;
}