ハフマンツリーの最小ヒープ実装

ハフマンツリー

意味

重み付きパス長 (WPL): バイナリ ツリーに n 個のリーフ ノードがあり、各リーフ ノードが重み W kを持ち、ルート ノードから各リーフ ノードまでの長さが L kであると仮定すると、各リーフ ノードの長さの合計重み付けされたパスの長さは次のとおりです: WPL = ∑ k = 1 n W k L k WPL=\sum_{k=1}^{n}W_kL_kWPL _ _=k = 1WL

特徴

  1. 次数 1 のノードはありません
  2. n 個のリーフ ノードを持つハフマン ツリーには、合計 2n-1 個のノードがあります。
  3. ハフマン ツリーの非リーフ ノードの左右のサブツリーは、交換後もハフマン ツリーのままです。
  4. 同じ重みセットに対して、異なるハフマン ツリーが存在します。

イニシャル

1
3
5
8

最初の合併

1
3
4
5
8

第二次合併

1
3
4
5
8
9

三次合併

1
3
4
5
8
9
17

レンプレート

指定された n 個の重みに従って、ルート ノードのみを含む n 個のバイナリ ツリーを構築します。最小ヒープを通じて、ルート ノードの重みが最小の 2 つのツリーを左右のサブツリーとして毎回選択し、新しいバイナリ ツリーを構築し、それを最小ヒープに挿入します。ツリーが 1 つだけ (ハフマン ツリー) になるまで、上記の手順を繰り返します。

#include <iostream>
using namespace std;

#define MaxSize 1000
int A[] = {
    
    1, 3, 5, 8};
int A_length = 4;

struct TreeNode
{
    
    
    int weight;
    TreeNode *left;
    TreeNode *right;
};
struct MinHeap
{
    
    
    TreeNode **data; //这是一个数组,每个元素的类型为(TreeNode*),是指向某个哈夫曼树的指针
    int size;
    int capacity;
};

MinHeap *CreateHeap();                   // 初始化堆
TreeNode *CreateHT();                    // 初始化哈夫曼树
TreeNode *Delete(MinHeap *H);            // 删除最小堆元素
void Insert(MinHeap *H, TreeNode *Huff); // 插入最小堆元素
void PreOrderTraversal(TreeNode *Huff);  // 先序遍历
void BuildMinHeap(MinHeap *H);           // 建堆
TreeNode *Huffman(MinHeap *H);           // 哈夫曼树的构建

int main()
{
    
    
    MinHeap *H;
    TreeNode *Huff;
    H = CreateHeap();
    Huff = Huffman(H);
    PreOrderTraversal(Huff);
    system("pause");
    return 0;
}

// 初始化堆
MinHeap *CreateHeap()
{
    
    
    MinHeap *H;
    H = new MinHeap;
    H->data = new TreeNode *[MaxSize + 1]; // 每个元素的类型为(TreeNode*)
    H->capacity = MaxSize;
    H->size = 0;
    // 给堆设置哨兵,哨兵要小于堆内所有值
    TreeNode *Huff;
    Huff = CreateHT();
    Huff->weight = INT_MIN;
    H->data[0] = Huff;
    return H;
}

// 初始化哈夫曼树
TreeNode *CreateHT()
{
    
    
    TreeNode *Huff;
    Huff = new TreeNode;
    Huff->weight = 0;
    Huff->left = NULL;
    Huff->right = NULL;
    return Huff;
}

// 插入最小堆元素(哈夫曼树)
void Insert(MinHeap *H, TreeNode *Huff)
{
    
    
    int weight = Huff->weight;
    int i = ++H->size;
    for (; H->data[i / 2]->weight > weight; i /= 2)
    {
    
    
        H->data[i] = H->data[i / 2];
    }
    H->data[i] = Huff;
}

// 删除最小堆元素
TreeNode *Delete(MinHeap *H)
{
    
    
    int parent, child;
    TreeNode *T = H->data[1];
    TreeNode *tmp = H->data[H->size--];
    for (parent = 1; parent * 2 <= H->size; parent = child)
    {
    
    
        child = 2 * parent;
        if ((child != H->size) && (H->data[child + 1]->weight < H->data[child]->weight))
            child++;
        if (H->data[child]->weight >= tmp->weight)
            break;
        else
            H->data[parent] = H->data[child];
    }
    H->data[parent] = tmp;
    return T;
}

// 建堆
void BuildMinHeap(MinHeap *H)
{
    
    
    TreeNode *Huff;
    for (int i = 0; i < A_length; i++)
    {
    
    
        Huff = CreateHT();
        Huff->weight = A[i];
        Insert(H, Huff);
    }
}

void PreOrderTraversal(TreeNode *Huff)
{
    
    
    if (Huff)
    {
    
    
        cout << Huff->weight << " ";
        PreOrderTraversal(Huff->left);
        PreOrderTraversal(Huff->right);
    }
}

//构建哈夫曼树
TreeNode *Huffman(MinHeap *H)
{
    
    
    TreeNode *T;
    BuildMinHeap(H);
    int times = H->size;
    // 做times-1次合并
    for (int i = 1; i < times; i++)
    {
    
    
        T = new TreeNode;
        T->left = Delete(H);
        T->right = Delete(H);
        T->weight = T->left->weight + T->right->weight;
        Insert(H, T);
    }
    T = Delete(H);
    return T;
}

おすすめ

転載: blog.csdn.net/leoabcd12/article/details/117821568