算法之旅,直奔贪心

哈夫曼树

  • 引言

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值