【问题标题】:Where does my Huffman encoding method go wrong?我的霍夫曼编码方法哪里出错了?
【发布时间】:2020-10-30 13:08:29
【问题描述】:

我正在尝试编写 Huffman 字符串编码算法。

我的解决方案是这样工作的:

  1. 由于字符串中的每个字母都有一个与之关联的特殊二进制代码,因此搜索二叉树,当找到一个字母时,将其添加到带有二进制代码的映射中。 (我出错的地方在这里
  2. 对字符串进行迭代,并为每个字母关联与映射字母的键关联的值。

我没有在某处打印树,即使很难,它也可以帮助你,但这是我得到的字符串 abracadabra,以及我应该得到的:

正确代码:000010000110110101111101011000111110110100111011101100101101110000110000110111100101111101010010

我得到了什么: 00001000111011010110101111010101100011101011010

这是我的代码:

#include <algorithm>
#include <map>

string codes = "";

void getMapCharBinaryCode(Node root, string &prefix, map <char, string> &m){
    if(!root) return;
    if(root->value){
        if(!m.count(root->value)){
            m[root->value] = prefix;
            prefix = "";
        } 
    }
    if(root->leftChild){
        getMapCharBinaryCode(root->leftChild, prefix += "0",m);
    }
    if(root->rightChild){
        getMapCharBinaryCode(root->rightChild, prefix += "1",m);
    }
   
}

string encode(string text, Node tree){
    // text is "abracadabra"
    // create map for each char -> binary code
    map<char, string> m;
    string prefix = "";
    getMapCharBinaryCode(tree, prefix, m);
    
    // iterate on text and assign each letter with binary code from map
    for(int i = 0; i < text.size(); i++) {
        codes += m[text[i]];
    }
    return codes;
}

【问题讨论】:

  • 首先尝试最小化创建错误输出所需的输入。然后使用调试器逐语句逐句执行代码,同时监视变量及其值,以查看出现问题的时间和位置。
  • 输入text是什么?
  • 请提供minimal reproducible example,包括合适的输入,以演示问题。
  • 嗨,Yolan,欢迎来到 Stack Overflow。我很高兴马克给出的答案对你有用(这是一个很好的答案)。但是,将更正的代码添加到您的问题中并不是我们的“风格”——这可能被视为以某种方式“破坏”了连续性。您将答案标记为“已接受”就足够了 - 这样,查看此 Q/A 的其他人就会知道它按预期工作。
  • 虽然 Yolan 可以,如果他们愿意,可以用更正后的代码为他们自己的问题发布 答案

标签: c++ algorithm huffman-code


【解决方案1】:

当您使用prefix = "" 保存叶子时,您正在破坏prefix 中的代码,当您从树中退回并转到下一个分支时需要该代码。

您可以为prefix 维护一个单独的存储区域,通过引用传递它。但是,您需要在上下树时管理prefix 的长度,并且您不需要添加0,然后将1 添加到that 以供两者使用分支,为右分支添加 01 而不是 1

作为起点,您应该只通过值传递prefix,这会产生副本,但在管理中不需要小心。去掉 &amp; 并将 prefix += 替换为 prefix +。摆脱prefix = "",然后它什么都不做。

【讨论】:

  • @YolanMaldonado 请不要编辑问题以包含答案
  • 这是一个非常好的建议 :) 我认为 OP 没有收到您的评论的通知。将此评论复制到对 OP 问题的评论中会不会太麻烦?我认为他们会从中受益匪浅,他们最终可能会提出一个真正的答案。谢谢:)
  • @yolanmaldonado 现在你已经开始工作了,你可以上下运行一个引用的prefix,这样效率更高。您需要为左分支添加一个字符,然后为右分支替换该字符(而不是添加另一个),然后在返回之前删除该字符,以恢复@ 987654335@ 进入例程时的状态。处理叶子时不要乱用prefix
  • @MarkAdler 感谢您编辑评论以包含对 OP 的 ping,我很感激 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多