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;
}