我的霍夫曼编码方法在哪里出错?

问题描述

我正在尝试编写霍夫曼字符串编码算法。

我的解决方案是这样的:

  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;
}

解决方法

使用prefix保存叶子时,您正在销毁prefix = ""中的代码,在该叶子上放回树并转到下一个分支时需要使用该代码。

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

作为起点,您应该只按值传递prefix,该值可以创建副本,但在管理上无需特别注意。摆脱&并将prefix +=替换为prefix +。摆脱prefix = "",然后什么也不做。