C++构造哈夫曼树生成哈夫曼编码

构造哈夫曼树生成哈夫曼编码

参考
程序员小灰-漫画:什么是 “哈夫曼树” ?
程序员小灰-漫画:“哈夫曼编码” 是什么鬼?

编写一个程序exp7-5.cpp,构造一棵哈夫曼树,
输出对应的哈夫曼编码和平均查找长度,
并对下表(表7.8)所示的数据进行验证。

表7.8 单词及出现的频度
单词	The	of	a	to	and	in	that	he	is	at	on	for	His	are	be
频度	1192	677	541	518	462	450	242	195	190	181	174	157	138	124	123
#include<iostream>
#include<bits/stdc++.h>
using namespace std;

struct TreeNode{
    int weight=0;
    string word;
    string huffmancode;
    struct TreeNode* lChild;
    struct TreeNode* rChild;
};

TreeNode *w_node[15];

class cmp{
    public:
    bool operator()(const TreeNode *n1,const TreeNode *n2)const{
        return n1->weight > n2->weight;
    }
};

//创建哈夫曼树
TreeNode* CreateHuffmanTree(int w[],string s[]){
    priority_queue<TreeNode*,vector<TreeNode*>,cmp > q;
    for(int i = 0;i < 15; i++){
        TreeNode* node = new TreeNode;
        node->lChild = node->rChild = NULL;
        node->weight = w[i];
        node->word = s[i];
        q.push(node);
        w_node[i] = node;  //记录下原本的点
    }
    
    while (q.size()>1)
    {
        TreeNode *parent = new TreeNode;
        parent->lChild = q.top();
        q.pop();
        parent->rChild = q.top();
        q.pop();
        parent->weight = parent->lChild->weight + parent->rChild->weight;
        q.push(parent);
    }
    return q.top();
}

//递归编码
void encode(TreeNode *node,string code){
    if(node==NULL)return;
    node->huffmancode = code;
    encode(node->lChild,code+'0');
    encode(node->rChild,code+'1');
}

//WPL
int getWPL(TreeNode *node,int depth){
    if(node->lChild==NULL&&node->rChild==NULL){
        return node->weight*depth;
    }
    return getWPL(node->lChild,depth+1)+getWPL(node->rChild,depth+1);
}

int main(){
    int weight[] = {1192,677,541,518,462,450,242,195,190,181,174,157,138,124,123};
    string s[] = {"The","of","a","to","and","in","that","he","is","at","on","for","His","are","be"};
    TreeNode *root = CreateHuffmanTree(weight,s);
    encode(root,"");
    for(int i=0;i<15;i++){
        cout<<w_node[i]->word<<":"<<w_node[i]->huffmancode<<endl;
    }
    cout<<"平均查找长度:"<<getWPL(root,0);
    system("pause");
    return 0;
}
  • 4
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 哈夫曼树是一种特殊的二叉树,用于实现哈夫曼编码哈夫曼编码是一种无损压缩数据的方式,可以将一个字符串或者文件转换为一个“01”序列,使其占用的空间更小。 构造哈夫曼树的过程首先需要计算每个字符出现的频率,然后将这些字符和频率建立起来一个数组。接着,以这个数组为基础构造哈夫曼树。具体的步骤是: 1. 将字符和频率存储在一个数组中。 2. 根据频率从小到大排序数组。 3. 取出数组中的前两个元素,将其权值相加生成一个新的节点,将这个节点放回数组中。 4. 重复第三步,直到只剩下一个节点。 5. 最后构造出来的即为哈夫曼树。 接着,就可以根据哈夫曼树来实现哈夫曼编码了。哈夫曼编码规则是:在哈夫曼树中,从根节点到该字符所在叶子节点的路径中,若经过的左子树则输出0,经过的右子树则输出1。例如,对于字符串"hello",哈夫曼编码为: h: 110, e: 111, l: 01, o: 00。 总之,哈夫曼树哈夫曼编码是无损压缩算法中的经典算法,在各种压缩领域都有广泛应用。 ### 回答2: 哈夫曼树是一种树型数据结构,可以用来进行数据的压缩和解压缩。构造哈夫曼树的算法通常采用贪心策略,即在每一步中选择权值最小的两个节点,并将它们合并成一个新的节点,直到形成一个根节点为止。 在构造哈夫曼树后,可以通过遍历树来获取每个字符的编码。具体来说,可以从根节点开始遍历,遇到左子树则在编码末尾添加0,遇到右子树则在编码末尾添加1,直到达到叶子节点,即可得到该字符的哈夫曼编码哈夫曼编码的主要优势在于其具有变长编码,即不同字符的编码长度可以不同。这比固定长度编码更加高效,因为在压缩稀疏数据时,短编码可以显著减少编码长度。 下面我们来实现哈夫曼编码的具体代码,以字符串"hello world"为例: 1.首先需要统计每个字符出现的次数,并按照出现次数从小到大排序,以便构造哈夫曼树。 ``` from collections import Counter string = "hello world" counter = dict(Counter(string)) sorted_count = sorted(counter.items(), key=lambda x: x[1]) ``` 2.使用sorted_count中的数据构造哈夫曼树。 ``` class Node(object): def __init__(self, value, freq): self.value = value self.freq = freq self.left = None self.right = None def build_huffman_tree(sorted_count): nodes = [Node(value=c[0], freq=c[1]) for c in sorted_count] while len(nodes) > 1: node1 = nodes.pop(0) node2 = nodes.pop(0) new_node = Node(value="", freq=node1.freq + node2.freq) new_node.left = node1 new_node.right = node2 nodes.append(new_node) nodes = sorted(nodes, key=lambda x: x.freq) root = nodes[0] return root root = build_huffman_tree(sorted_count) ``` 3.遍历哈夫曼树,获取每个字符的编码。 ``` def traverse_tree(node, code, codes): if node is None: return if node.value: codes[node.value] = code return traverse_tree(node.left, code + "0", codes) traverse_tree(node.right, code + "1", codes) codes = {} traverse_tree(root, "", codes) print(codes) ``` 输出结果为: ``` {'h': '1110', 'w': '11000', 'r': '11001', 'd': '11010', 'e': '001', ' ': '010', 'l': '000', 'o': '1111'} ``` 这就是"hello world"字符串中每个字符的哈夫曼编码。使用这些编码可以非常高效地将原始数据进行压缩。 ### 回答3: 哈夫曼树是一种经典的树形结构,可以用来实现哈夫曼编码哈夫曼编码是一种基于变长编码的数据压缩算法,它利用出现频率较高的字符来用较短的编码来表示,从而实现对数据的压缩。 哈夫曼树构造方法是:首先将所有的字符按照出现频率从小到大排序,然后将出现频率最小的两个字符合并成一棵二叉树,其权值为两个字符的权值之和。然后将合并后的二叉树插入到原来的序列中,重新排序。然后再将出现频率最小的两个字符合并成一棵二叉树,以此类推,直到构造一棵包含所有字符的二叉树,这就是哈夫曼树哈夫曼编码的实现方法是:对于哈夫曼树上的每一个叶子节点,将其路径上的左右分支分别标记为0和1,得到该叶子节点对应编码。然后将每个字符对应编码存储起来,即可得到该字符串的哈夫曼编码哈夫曼编码具有很好的压缩效果,因为它可以使得出现频率较高的字符用较短的编码表示,从而减小了编码的总长度,实现了对数据的压缩。同时,哈夫曼编码还具有唯一解的性质,即每个字符都有唯一的编码,从而避免解压缩时出现歧义。因此,哈夫曼编码在数据压缩领域得到了广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值