哈夫曼树

哈弗曼树(Huffman tree):是最优二叉树,加权路径最短的二叉树。

贪心算法:是指在问题求解时,总是做出当前看起来最好的选择,即为贪心算法做出的不是整体最优的选择,而是某种意义上的局部最优解,贪心算法不是对所有的问题都能得到整体最优解。

思想:这里使用贪心算法构建哈弗曼树,运用最小堆的思想,建立最小堆,每次从堆中找最小的两个节点构造新结点,新结点再放回堆中,并连接两个旧的结点,按相同方法依次连接,直到剩下最后一个结点作为根结点,最后构造完成为哈夫曼树。

代码如下(此处引用前自己构造的堆,引用头文件Heap.h,前面博客已经写过):


#include<iostream>
#include <assert.h>
#include "Heap.h"
template <class T>
struct HuffmanTreeNode
{
	T _weight;   //权重
	//三叉链
	HuffmanTreeNode<T>* _left;   
	HuffmanTreeNode<T>* _right;
	HuffmanTreeNode<T>* _parent;

	HuffmanTreeNode(const T& x)
		:_weight(x)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
	{}
};

template <class T>
class HuffmanTree
{
	typedef HuffmanTreeNode<T> Node;
public:
	HuffmanTree()
		:_root(NULL)
	{}
	HuffmanTree(T* a,size_t n,const T& invalid)
	{
		assert(a);
		struct Compare
		{
			bool operator()(Node* l1,Node* l2)
			{
				return l1->_weight<l2->_weight;   //比较结点中的权值
			}
		};
		//建小堆
		Heap<Node*,Compare> hp;//堆中存储哈夫曼结点指针
		for(size_t i=0;i<n;++i)
		{
			if(a[i]!=invalid)
			{
				hp.Push(new Node(a[i]));
			}
		}
		//选最小的两个数据建哈夫曼树
		while(hp.Size()>1)
		{
			Node* left=hp.Top();
			hp.Pop();
			Node* right=hp.Top();
			hp.Pop();
			Node* parent=new Node(left->_weight+right->_weight);
			hp.Push(parent);

			parent->_left=left;
			parent->_right=right;
			left->_parent=parent;
			right->_parent=parent;
		}
		_root=hp.Top();//堆里最后一个结点即为根结点
		hp.Pop();
	}

	~HuffmanTree()
	{
		_Destory(_root);
		_root=NULL;
	}

	Node* GetRoot()
	{
		return _root;
	}
protected:
	void _Destory(Node* root)
	{
		if(root==NULL)
			return;
		_Destory(root->_left);
		_Destory(root->_right);
		if(root->_left==NULL&&root->_right==NULL)
		{
			delete root;
			root=NULL;
		}
			
	}

protected:
	Node* _root;
};

void TestHuffman()
{
	int a[]={0,1,2,3,4,0,0,};
	HuffmanTree<int> Htree(a,sizeof(a)/sizeof(a[0]),0); 
}
int main()
{
	TestHuffman();
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值