哈夫曼树之C++实现

关于哈夫曼树的讲解请参考上篇《三步学通哈夫曼树》(https://blog.youkuaiyun.com/helloworldchina/article/details/105210054),这里笔者仅补充一下C++代码的实现。见下:

1 c++代码

#include <iostream>
#include <iostream>
#include <iomanip>
using namespace std;

bool pr=false;//true  打印测试日志
//哈夫曼树的结构
typedef struct
{
    int weight;    // 权值
    int parent, lChild, rChild;    // 双亲及左右孩子的下标
}HTNode, *HuffmanTree;

//输出哈夫曼树各结点信息
void Print(HuffmanTree hT)
{
    std::cout << "index weight parent lChild rChild" << std::endl;
    std::cout << left;    // 左对齐输出
    for(int i = 1, m = hT[0].weight; i <= m; i++)
    {
        std::cout << setw(5) << i << " ";
        std::cout << setw(6) << hT[i].weight << " ";
        std::cout << setw(6) << hT[i].parent << " ";
        std::cout << setw(6) << hT[i].lChild << " ";
        std::cout << setw(6) << hT[i].rChild << std::endl;

    }
}

// 选择权值最小的两颗树
void SelectMin(HuffmanTree hT, int k, int &index1, int &index2)
{
    index1 = index2 = 0;
    int i,j;
    for(j = 1; j <= k;j++)
    {//使index1,index2分别指向hT中最前面的两个无双亲的结点
        if(0 == hT[j].parent)
        {
            if( 0== index1)
            {
                index1 = j;
            }
            else
            {
                index2 = j;
                break;
            }
        }
    }

    if(hT[index1].weight > hT[index2].weight)
    {//使结点index1的权小于index2的权
        int t = index1;
        index1 = index2;
        index2 = t;
    }

    for(i =j+1; i<k;  i++){//继续查找没有双亲且权值最小的两个结点,将其地址记在index1和index2中
        if(0 == hT[i].parent)
        {
            if(hT[i].weight < hT[index1].weight)
            {
                index2 = index1;
                index1 = i;
            }else if(hT[i].weight < hT[index2].weight)
            {
                index2 = i;
            }
        }
    }
}


// 构造有n个权值(叶子结点)的哈夫曼树
int CreateHufmanTree(HuffmanTree &hT)
{
    std::cout << "请输入权值的数量n=? " << std::endl;
    int n, k;//n 权值数(叶子结点数)  k结点的个数
    cin >> n;
    if (n<=1) return 0;
    k = 2*n - 1;
    //创建存储哈夫曼树的数组
    hT = new HTNode[k + 1];    // 0号结点不使用
    //给数组赋初值0
    for(int i = 1; i <= k; i++){
        hT[i].parent = hT[i].lChild = hT[i].rChild = 0;
    }
    std::cout << "请依次输入权值,并回车确认" << std::endl;
    for(int i = 1; i <= n; i++){
        cin >> hT[i].weight;    // 输入权值
    }
    hT[0].weight = k;    // 用0号结点保存结点数量


    if (pr)
    {
        std::cout << "打印初始的数组:" << std::endl;
        Print(hT);
    }

    /****** 初始化完毕, 创建哈夫曼树 ******/
    for(int i = n + 1; i <=k; i++)
    {
        int index1, index2;
        SelectMin(hT, i, index1, index2);

        hT[index1].parent = hT[index2].parent = i;
        hT[i].lChild = index1; hT[i].rChild = index2;    // 作为新结点的孩子
        hT[i].weight = hT[index1].weight + hT[index2].weight;    // 新结点为左右孩子结点权值之和

        if (pr)
        {
            std::cout << "打印构建哈夫曼树过程中的数组:" << std::endl;
            std::cout << "i=" <<i<<std::endl;
            std::cout << "index1=" <<index1<<";index2="<<index2<<std::endl;
            Print(hT);
        }
    }
    return 1;
}

int HuffmanTreeWPL_w(HuffmanTree hT, int i, int deepth)
{
    if(hT[i].lChild == 0 && hT[i].rChild == 0)
    {
        return hT[i].weight * deepth;
    }
    else
    {
        return HuffmanTreeWPL_w(hT, hT[i].lChild, deepth + 1) + HuffmanTreeWPL_w(hT, hT[i].rChild, deepth + 1);
    }
}

// 计算WPL(带权路径长度)
int HuffmanTreeWPL(HuffmanTree hT)
{
    return HuffmanTreeWPL_w(hT, hT[0].weight, 0);
}



// 销毁哈夫曼树
void DestoryHuffmanTree(HuffmanTree &hT)
{
    delete[] hT;
    hT = NULL;
}

int main()
{

    HuffmanTree hT;
    if (CreateHufmanTree(hT))
    {
        std::cout << "打印哈夫曼树数组:" << std::endl;
        Print(hT);
        std::cout << "WPL = " << HuffmanTreeWPL(hT) << std::endl;
        DestoryHuffmanTree(hT);
    } else std::cout << "输入有误,不能创建哈夫曼树!" << std::endl;

    return 0;
}

2 运行结果

在这里插入图片描述

### 哈夫曼C++实现 哈夫曼编码是一种广泛应用于数据压缩的技术,通常通过数组来构建哈夫曼[^1]。下面是一个简单的哈夫曼C++中的实现例子: ```cpp #include <iostream> #include <vector> #include <queue> struct Node { char data; int freq; Node *left, *right; Node(char c, int f) : data(c), freq(f), left(nullptr), right(nullptr) {} }; // 自定义比较器用于优先队列 struct compare { bool operator()(Node* l, Node* r) { return l->freq > r->freq; } }; void generateCodes(Node* root, std::string str, std::unordered_map<char, std::string> &huffmanCode) { if (!root) return; if (!root->left && !root->right) huffmanCode[root->data] = str; generateCodes(root->left, str + "0", huffmanCode); generateCodes(root->right, str + "1", huffmanCode); } std::map<char, int> frequencyMap(const std::string& text) { std::map<char, int> frequency; for (char ch : text) ++frequency[ch]; return frequency; } Node* buildHuffmanTree(const std::map<char, int>& frequency) { std::priority_queue<Node*, std::vector<Node*>, compare> minHeap; for (auto pair: frequency) minHeap.push(new Node(pair.first, pair.second)); while (minHeap.size() != 1) { Node *left = minHeap.top(); minHeap.pop(); Node *right = minHeap.top(); minHeap.pop(); Node *newNode = new Node(&#39;$&#39;, left->freq + right->freq); newNode->left = left; newNode->right = right; minHeap.push(newNode); } return minHeap.top(); } void print(std::unordered_map<char, std::string> huffmanCode) { for (auto pair : huffmanCode) std::cout << pair.first << ": " << pair.second << "\n"; } int main() { std::string text = "this is an example for huffman encoding"; auto frequency = frequencyMap(text); Node* root = buildHuffmanTree(frequency); std::unordered_map<char, std::string> huffmanCode; generateCodes(root, "", huffmanCode); print(huffmanCode); return 0; } ``` 此代码片段展示了如何创建一个基于给定字符串频率表的哈夫曼,并生成相应的二进制编码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值