Huffman樹的創建

運用了小堆堆的基本操作

#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;
};
發佈了109 篇原創文章 · 獲贊 17 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章