HuffmanTree的实现

数据结构书上的HuffmanTree的实现算法是O(n ^ 2)的复杂度,比较好理解,也好实现,所以就不赘述了,在这里说一下O(nlogn)的复杂度的HuffmanTree的实现方法:构造一个二叉堆,维护小顶堆。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef struct hNode
{
    int weight;
    int lc, rc;
} *HuffmanTree;

HuffmanTree CreateHuffmanTree(const int w[], int n);  //创建一棵HuffmanTree
void BuildHeap(HuffmanTree t, int n);  //构造一个二叉堆:小顶堆
void PercDown(HuffmanTree t, int pos, int n);  //构造二叉堆的功能子函数
void DeleteMin(HuffmanTree t, int len);  //删除二叉堆的根,并通过上移使得新得到的序列仍为二叉堆
void insertHfNode(HuffmanTree t, int len, struct hNode x);  //把x插入到原长度为len - 1的二叉堆
void Preorder(HuffmanTree t, int p, unsigned long long &sum);  //先序遍历HuffmanTree,累计非叶子节点的值

int main()
{
    int n;
    scanf("%d", &n);
    int *a = new int[n];
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);
    HuffmanTree hT = CreateHuffmanTree(a, n);
    unsigned long long sum = 0;
    Preorder(hT, 1, sum);  
    if (n == 1) sum = a[0];
    cout << sum << endl;
    return 0;
}

HuffmanTree CreateHuffmanTree(const int w[], int n)
{
    HuffmanTree hT = new struct hNode[2 * n];  //第一个节点不用
    for (int i = 0; i < n; ++i)
    {
        hT[i + 1].weight = w[i];
        hT[i + 1].lc = hT[i + 1].rc = 0;
    }
    BuildHeap(hT, n);

    struct hNode add;
    int left = n;
    int right = n;
    while (left > 1)  //此处通过减小和增大left的值来改变二叉堆的大小
    {
        hT[++right] = hT[1];
        add.weight = hT[1].weight;
        add.lc = right;  //存储左孩子下标

        DeleteMin(hT, left--);

        hT[left + 1] = hT[1];
        add.weight += hT[1].weight;
        add.rc = left + 1;  //存储右孩子下标  

        DeleteMin(hT, left);

        insertHfNode(hT, left, add);
    }
    return hT;
}

void BuildHeap(HuffmanTree t, int len)
{
    for (int i = len / 2; i > 0; --i)
    {
        PercDown(t, i, len);
    }
}

void PercDown(HuffmanTree t, int pos, int len)
{
    int child;
    struct hNode min = t[pos];
    while (pos * 2 <= len)
    {
        child = pos * 2;
        if (child != len && t[child + 1].weight < t[child].weight)
            child++;
        if (min.weight > t[child].weight)
            t[pos] = t[child];
        else
            break;
        pos = child;
    }
    t[pos] = min;
}

void DeleteMin(HuffmanTree t, int len)
{
    struct hNode last = t[len--];  //二叉堆的最后一个元素
    int child, pos = 1;
    while (pos * 2 <= len)  //把二叉堆的某些元素往前移,使得新得到的序列仍为二叉堆
    {
        child = pos * 2;
        if (child != len && t[child + 1].weight < t[child].weight)  //若i有右儿子,且右儿子小于左儿子,c指向右儿子
            child++;
        if (last.weight > t[child].weight)  //若i的小儿子小于二叉堆的最后一个元素,把其移到i的位置
            t[pos] = t[child];
        else
            break;
    }
    t[pos] = last;  //把二叉堆的最后一个元素放到适当的空位,此时得到的序列仍为二叉堆
}

void insertHfNode(HuffmanTree t, int len, struct hNode x)
{
    int i;
    for (i = len; i / 2 > 0 && t[i / 2].weight > x.weight; i /= 2)
        t[i] = t[i / 2];
    t[i] = x;
}

void Preorder(HuffmanTree t, int p, unsigned long long & sum)
{
    if (t[p].lc > 0)
    {
        sum += t[p].weight;
        Preorder(t, t[p].lc, sum);  //遍历左子树
        Preorder(t, t[p].rc, sum);  //遍历右子树
    }
}


这里是用 C++ 实现HuffmanTree的代码,包括编码和解码的功能。 ```cpp #include <iostream> #include <string> #include <queue> #include <map> using namespace std; // 定义Huffman节点结构体 struct HuffmanNode { char data; // 字符 int weight; // 权重 HuffmanNode *left, *right; // 左右子节点 HuffmanNode(char c, int w) :data(c), weight(w), left(nullptr), right(nullptr) {} HuffmanNode(int w) :data('\0'), weight(w), left(nullptr), right(nullptr) {} }; // 定义比较函数,用于优先队列排序 struct Compare { bool operator() (HuffmanNode* a, HuffmanNode* b) { return a->weight > b->weight; } }; // 建立HuffmanHuffmanNode* buildHuffmanTree(const string& str) { if (str.empty()) { return nullptr; } // 统计字符出现频率 map<char, int> freq; for (char c : str) { freq[c]++; } // 初始化优先队列,每个字符作为一个节点 priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> pq; for (auto it : freq) { pq.push(new HuffmanNode(it.first, it.second)); } // 构建Huffman树 while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode(left->weight + right->weight); parent->left = left; parent->right = right; pq.push(parent); } // 返回根节点 return pq.top(); } // 递归遍历Huffman树,生成编码表 void generateHuffmanCode(HuffmanNode* node, string code, map<char, string>& encodeTable) { if (!node) { return; } if (node->data != '\0') { encodeTable[node->data] = code; } generateHuffmanCode(node->left, code + '0', encodeTable); generateHuffmanCode(node->right, code + '1', encodeTable); } // Huffman编码 string huffmanEncode(const string& str) { if (str.empty()) { return ""; } // 建立Huffman树和编码表 HuffmanNode* root = buildHuffmanTree(str); map<char, string> encodeTable; generateHuffmanCode(root, "", encodeTable); // 生成编码结果 string result; for (char c : str) { result += encodeTable[c]; } // 释放内存 delete root; return result; } // Huffman解码 string huffmanDecode(const string& code, HuffmanNode* root) { if (code.empty() || !root) { return ""; } string result; HuffmanNode* node = root; for (char c : code) { if (c == '0') { node = node->left; } else { node = node->right; } if (node->data != '\0') { result += node->data; node = root; } } return result; } int main() { // 模拟发送端 string str = "I love you"; string code = huffmanEncode(str); cout << code << endl; // 模拟接收端 HuffmanNode* root = buildHuffmanTree(str); string message = huffmanDecode(code, root); cout << message << endl; // 释放内存 delete root; return 0; } ``` 运行结果: ``` 01101111011110011100000010111100011100100001 it is a dog ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值