Huffman 树

Huffman树:又称最优二叉树,是加权路径长度最短的二叉树    由于每次都要找最小的两个数,所以用最小堆方便求解
#pragma once
#include<cassert>
#include<vector>
using namespace std;
template<typename T>
struct Less
{
	bool operator()(const T& l,const T& r)
	{
		return l<r;
	}
};
template<typename T>
struct Great
{
	bool operator()(const T& l,const T& r)
	{
		return l>r;
	}
};
template<typename T,class Compare=Less<T>>
class Heap
{
public:
	Heap()
	{}
	Heap(T* a,int size)
	{
		a.reserve(size);
		for(int i=0;i<size;i++)
		{
			a.push_back(a[i]);
		}
		for(int i=(size-2)/2;i>=0;--i)
		{
			AdjustDown(i,size);
		}
	}
	void Push(const T& x)
	{
		a.push_back(x);
		AdjustUp(a.size()-1);//插入尾部,在从最后一个开始向上调整
	}
	void Pop()//取出最小的元素
	{
		assert(!a.empty());
		swap(a[0],a[a.size()-1]);
		a.pop_back();
		if(a.size()>1)
		{
			AdjustDown(0,a.size());
		}
	}
	size_t Size()
	{
		return a.size();
	}
	bool Empty()
	{
		return a.empty();
	}
	const T& Top()
	{
		assert(!a.empty());
		return a[0];
	}
protected:
	void AdjustDown(int root,int size)
	{
		assert(!a.empty());
		int parent=root;
		int child=parent*2+1;
		while(child<size)
		{
			if((child+1)<size&&Compare()(a[child+1],a[child]))
				child++;
			if(Compare()(a[child],a[parent]))
			{
				swap(a[child],a[parent]);
				parent=child;
				child=parent*2+1;
			}
			else
			{
				break;
			}
		}
	}
	void AdjustUp(int child)
	{
		assert(!a.empty());
		while(child>0)
		{
			int parent=(child-1)/2;
			if(Compare()(a[child],a[parent]))
			{
				swap(a[child],a[parent]);
				child=parent;
			}
			else
			{
				break;
			}
		}
	}
private:
	vector<T> a;
};

#pragma once
#include<queue>
#include"heap.cpp"
#include<iostream>
using namespace std;
template<typename T>
struct HuffmanNode
{
    T _weight;
	HuffmanNode<T>* _left;
	HuffmanNode<T>* _right;
	HuffmanNode<T>* _parent;
	HuffmanNode(const T& weight)
		:_weight(weight)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
	{}
};
template<typename T>
class HuffmanTree
{
public:
	HuffmanTree()
		:root(NULL)
	{}
	void CreateHuffmanTree(T *a,size_t size,const T& invalid=T())
	{
		//最小堆的比较方式
		struct Compare
		{
			bool operator()(HuffmanNode<T>*& l,HuffmanNode<T>*& r)
			{
				return l->_weight < r->_weight;
			}
		};
		//将所有值构造成结点放入最小堆中,仿函数做比较器
		Heap<HuffmanNode<T>*,Compare> minHeap;
		for(size_t i=0;i<size;i++)
		{
			if(a[i]!=invalid)
			{
				HuffmanNode<T>* node=new HuffmanNode<T>(a[i]);
				minHeap.Push(node);
			}
		}
		//根据Huffman算法,从堆里取出最小的两个数,删除,将这两个数构成的结点加入堆中
		HuffmanNode<T>* frist=NULL;
		HuffmanNode<T>* second=NULL;
		HuffmanNode<T>* parent=NULL;
		while(minHeap.Size()>1)
		{
			frist=minHeap.Top();
			minHeap.Pop();
			second=minHeap.Top();
			minHeap.Pop();
			parent=new HuffmanNode<T>(frist->_weight+second->_weight);
			parent->_left=frist;
			parent->_right=second;
			frist->_parent=parent;
			second->_parent=parent;
			minHeap.Push(parent);
		}
		root=minHeap.Top();
	}
	//层序遍历打印二叉树
	void Level()
	{
		queue<HuffmanNode<T>*> q;
		HuffmanNode<T>* cur=root;
		q.push(cur);
		while(!q.empty())
		{
			HuffmanNode<T>* front=q.front();
			q.pop();
			cout<<front->_weight<<" ";
			if(front->_left)
				q.push(front->_left);
			if(front->_right)
				q.push(front->_right);
		}
		cout<<endl;
	}
	HuffmanNode<T>* GetRoot()
	{
		return root;
	}
	~HuffmanTree()
	{
		if(root!=NULL)
		{
			Destory(root);
		}
    }
protected:
	void Destory(HuffmanNode<T>* root)
	{
		if(root==NULL)
			return;
		HuffmanNode<T>* cur=root;
		Destory(cur->_left);
		Destory(cur->_right);
		delete cur;
		cur=NULL;
	}
private:
	HuffmanNode<T>* root;
};
 void TestHuffmanTree()
{
	int a[10] = {2, 3, 6, 0 ,4, 5, 1, 9, 7, 8};
	HuffmanTree<int> tree;
	tree.CreateHuffmanTree(a, 10, -1);
	tree.Level();
}
 int main()
{
	TestHuffmanTree();
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值