運用了小堆堆的基本操作
#include<stdio.h>
#include<iostream>
using namespace std;
#include"heap.cpp"//引用堆的創建文件
template<class T>
struct Node
{
Node(T weight,T data = T())
:_pLeft(NULL)
,_pRight(NULL)
,_weight(weight)
,_data(data)
{}
Node* _pLeft;
Node* _pRight;
T _data;
T _weight;
};
template<class T>
struct ComplareNode
{
bool operator()(Node<T>* pLeft,Node<T>* pRight)
{
return pLeft->_weight<pRight->_weight;
}
};
template<class T>
class HuffmanTree
{
public:
HuffmanTree()
:_pRoot(NULL)
{}
HuffmanTree(const T array[],size_t size)
{
//首先,我們要將數組中所有權值的數轉化爲節點的森林
//然後選擇權值最小的兩個節點做爲左右子樹組建成一棵樹,根節點的權值爲這兩個節點的權值之和,將該樹放入我們的森林裏
//再繼續重複上一步驟,直到剩下最後一個節點,該節點就是一棵huffman樹的根節點
//針對於如何在森林中選取權值最小的兩個節點,我們可以根據我們剛剛學的堆來處理,用森另中的所有節點建立一個小堆,每次選取堆頂的元素
_CreateHuffmanTree(array,size);
}
private:
void _CreateHuffmanTree(const T array[],size_t size)
{
heap<Node<T>*,ComplareNode<T>> hp;//創建一個堆,用來存放森林
for(size_t idx=0; idx<size; ++idx)//將權值轉化爲節點存入堆中
{
hp.Insert(new Node<T>(array[idx]));
}
//存在問題!!!!我們前面實現的堆在調整時比較的是節點的data值
//因爲我們的vector裏存放的是T類型,但是我們現在vector裏存放的是Node<T>*,所以調整時不能再用 <和>直接比較
//如果直接比較比較的將是兩個地址,而我們要比較的則是節點的權值,但vector裏又不能存放權值,如果存放的是權值,
//新產生的樹將會丟失,蘇所以我們必須重新定義比較類
while(hp.Size()>1)
{
Node<T>* pLeft = hp.Top();//在堆中選取兩個最小權值的節點,作爲左右孩子組建成新的樹
hp.Remove();
Node<T>* pRight = hp.Top();
hp.Remove();
Node<T>* pParent = new Node<T>(pLeft->_weight+pRight->_weight);
pParent->_pLeft = pLeft;
pParent->_pRight = pRight;
hp.Insert(pParent);//將樹放入森林
}
_pRoot = hp.Top();
}
private:
Node<T>* _pRoot;
};