資料結構——哈夫曼樹實現
阿新 • • 發佈:2019-01-02
利用小堆實現哈夫曼樹
Heap.h
#pragma once
#include <vector>
#include <assert.h>
//仿函式
template<class T>
struct Less
{
bool operator()(const T& left,const T& right)
{
return left < right;
}
};
template<class T>
struct Greater
{
bool operator()(const T& left,const T& right)
{
return left > right;
}
};
template<class T,class Compare = Less<T>>
class Heap
{
public:
Heap()
{}
Heap(const T array[],size_t size)
{
_heap.resize (size);
for(int i=0;i<size;i++)
{
//_heap.push_back (array[i]);
_heap[i] = array[i];
}
int root = (_heap.size ()-2)>>1;
for(;root>=0;root--)
{
_AdjustDown(root);
}
}
size_t Size()const
{
return _heap.size ();
}
bool Empty()const
{
return _heap.empty ();
}
void Insert(const T& data)
{
//先尾插入元素
//再向上調整
_heap.push_back (data);
_AdjustUp(_heap.size ()-1);
}
void Remove()
{
//如果堆為空則不操作
if(_heap.size ()==0)
return ;
//如果只有根節點和其孩子則交換後直接刪除最後一個節點
if(_heap.size ()<=2)
{
std::swap (_heap[0],_heap[_heap.size ()-1]);
_heap.pop_back ();
}
//如果節點數大於2個,則先交換根元素和尾元素,再刪除尾元素,
//最後重新調整堆結構
else
{
std::swap (_heap[0],_heap[_heap.size ()-1]);
_heap.pop_back ();
//int root = (_heap.size ()-2)>>1;
//for(;root>=0;root--)
// _AdjustDown(root);
int child = _heap.size ()-1;
_AdjustUp(child);
}
}
const T& Top()const
{
assert(!Empty());
return _heap[0];
}
private:
void _AdjustDown(size_t parent)
{
size_t child = parent*2+1;
while(child<_heap.size ())
{
Compare com;
//如果右孩子存在則找左右孩子中最小的節點
if(child+1<_heap.size () && com(_heap[child+1],_heap[child]))
child+=1;
if(com(_heap[child],_heap[parent]))
{
std::swap (_heap[parent],_heap[child]);
parent = child;
child = parent*2+1;
}
else
return ;
}
}
void _AdjustUp(size_t child)
{
while(child>=1)
{
Compare com;
size_t parent = (child-1)>>1;
if(com(_heap[child],_heap[parent]))
std::swap (_heap[parent],_heap[child]);
child = parent;
}
}
private:
std::vector <T> _heap;
};
Huffman.h
#pragma once
#include "Heap.h"
#include <assert.h>
using namespace std;
template<class T>
struct Node
{
Node(const T& weight)
:_weight(weight)
,_pLeft(NULL)
,_pRight(NULL)
{}
T _weight;
T _data;
Node<T>* _pLeft;
Node<T>* _pRight;
};
template<class T>
class HuffmanTree
{
public:
HuffmanTree()
:_pRoot(NULL)
{}
HuffmanTree(const T array[],size_t size)
{
_Create(array,size);
}
private:
void _Create(const T array[],size_t size)
{
assert(array);
struct CompareNode
{
bool operator()(Node<T>* left,Node<T>* right)
{
return left->_weight < right->_weight;
}
};
Heap<Node<T>*,CompareNode> hp;
for(int i=0;i<size;i++)
{
Node<T>* node = new Node<T>(array[i]);
hp.Insert (node);
}
while(hp.Size()>1)
{
Node<T>* pLeft = hp.Top ();
hp.Remove ();
Node<T>* pRight = hp.Top ();
hp.Remove ();
Node<T>* parent = new Node<T>(pLeft->_weight+pRight->_weight);
parent->_pLeft = pLeft;
parent->_pRight = pRight;
hp.Insert (parent);
}
_pRoot = hp.Top();
}
private:
Node<T>* _pRoot;
};