要了解HuffmanTree,首先要了解几个概念:
1.二叉树的路径长度:从根结点到每个节点的路径长度之和。
2.带权路径长度:(从根结点到每个叶子结点的路径*每个叶子结点的权限)相加之和。
3.HuffmanTree:带权路径最小的树。
HuffmanTree的构造也用了堆的概念,在每次插入一个数据后,需要调整整棵树,来使得带权路径最小。
Heap:
#include <iostream>
#include <windows.h>
#include <vector>
#include <assert.h>
using namespace std;
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return left->_weight < right->_weight;
}
};
template<class T>
struct Greater
{
bool operator()(const T& left, const T& right)
{
return left->_weight > right->_weight;
}
};
// 小堆
template<class T, class Compare = Less<T>>
class Heap
{
public:
Heap()
{}
Heap(const T arr[], size_t size, const T& invalid)
{
_heap.resize(size);
for(size_t i=0; i<size; ++i)//先将所有的数都放入堆中
{
_heap[i] = arr[i];
}
int root = (_heap.size()-2)>>1;//将堆中的数据向下调整
for(; root>=0;--root)
_AdjustDown(root);
}
void Insert(const T& data)
{
_heap.push_back(data);
if(_heap.size() > 1)
_AdjustUp();
}
void Remove()
{
assert(!_heap.empty());
std::swap(_heap[0], _heap[_heap.size() - 1]);
_heap.pop_back();
if(_heap.size() > 1)
_AdjustDown(0);
}
size_t Size()const
{
return _heap.size();
}
bool Empty()const
{
return 0 == _heap.size();
}
const T& Top()const
{
return _heap[0];
}
void _AdjustDown(size_t parent)
{
size_t child = parent*2+1;
size_t size = _heap.size();
while(child < size)
{
if(child+1 < size && Compare()(_heap[child+1], _heap[child]))
child += 1;
if(Compare()(_heap[child], _heap[parent]))
{
std::swap(_heap[child], _heap[parent]);
parent = child;
child = parent*2 + 1;
}
else
return ;
}
}
void _AdjustUp()
{
size_t child = _heap.size()-1;
size_t parent = (child-1) >> 1;
while(child != 0)
{
if(Compare()(_heap[child], _heap[parent]))
{
std::swap(_heap[child], _heap[parent]);
child = parent;
parent = (child-1) >> 1;
}
else
return ;
}
}
private:
std::vector<T> _heap;
};
HuffmanTree:
#include "heap.h"
template<class T>
struct HuffmanTreeNode
{
HuffmanTreeNode(const T& weight)
: _weight(weight)
, _pLeft(NULL)
, _pRight(NULL)
, _pParent(NULL)
{}
T _weight; // 权值
HuffmanTreeNode<T>* _pLeft;
HuffmanTreeNode<T>* _pRight;
HuffmanTreeNode<T>* _pParent;
};
template<class T>
class HuffmanTree
{
typedef HuffmanTreeNode<T> Node;
public:
HuffmanTree()
: _pRoot(NULL)
{}
HuffmanTree(const T arr[], size_t size, const T& invalid)
{
_Create(arr, size, invalid);
}
~HuffmanTree()
{
_Destroy(_pRoot);
}
const Node* Root()const
{
return _pRoot;
}
private:
void _Create(const T arr[], size_t size, const T& invalid)
{
struct Compare
{
bool operator()(const Node* pLeft, const Node* pRight)
{
return pLeft->_weight < pRight->_weight;
}
};
Heap<Node*> hp;
for(size_t i=0; i<size; ++i)//先将所有的数都放入堆中
{
if(arr[i] != invalid)
hp.Insert(new Node(arr[i]));
}
while(hp.Size() > 1)
{
Node* pLeft = hp.Top();
hp.Remove();
Node* pRight = hp.Top();
hp.Remove();
Node* pParent = new Node(pLeft->_weight + pRight->_weight);
pLeft->_pParent = pParent;
pRight->_pParent = pParent;
pParent->_pLeft = pLeft;
pParent->_pRight = pRight;
hp.Insert(pParent);
hp._AdjustUp();
}
_pRoot = hp.Top();
}
void _Destroy(Node* & pRoot)
{
if(pRoot)
{
_Destroy(pRoot->_pLeft);
_Destroy(pRoot->_pRight);
delete pRoot;
pRoot == NULL;
}
}
protected:
Node* _pRoot;
};