2015-04-02 2 views
0

Я пытаюсь расшифровать дерево Хаффмана формы:Декодирование дерева Хаффмана

001A1C01E01B1D 

Я использую реализацию здесь: Efficient way of storing Huffman tree закодировать дерево в форме выше и декодировать его, а также ,

Это моя реализация этого:

HuffmanNode* HuffmanTree::decodeTree(string tree, int idx) { 
    cout << idx << endl; 
    if (tree[idx] == '1') { 
     idx += 2; 
     return new HuffmanNode(tree[idx - 1]); 
    } 
    else { 
     if (idx != tree.length() - 1) { 
      idx++; 
      HuffmanNode* leftChild = decodeTree(tree, idx); 
      idx++; 
      HuffmanNode* rightChild = decodeTree(tree, idx); 
      return new HuffmanNode(leftChild, rightChild); 
     } 
     else 
      return new HuffmanNode(tree[idx]); 
    } 
} 

Я получаю нарушение прав доступа, написание местоположение, когда функция раскручивается (On "вернуть новый HuffmanNode (дерево [IDX - 1]);"), и я надеюсь, что окончательное возвращение будет корнем дерева, но при дальнейшей проверке это, похоже, не так. Может ли кто-нибудь дать мне несколько указателей? (Каламбур не предназначен)

+0

Вы ожидаете, что idx будет использоваться между рекурсивными вызовами? если это так, вам нужно сделать ссылку в списке параметров. Кроме того, вы, вероятно, можете сделать с некоторыми проверками безопасности границ (с соответствующими ошибками); так как это означает, что это может быть вызвано любой строкой, заканчивающейся, например, «1». – Dave

ответ

1

Проблема с вашим кодом в том, что idx не изменяется внутри рекурсивных трасс. Передайте его в функцию, как int &: HuffmanNode* HuffmanTree::decodeTree(string tree, int &idx)

Существует и еще одна ошибка в коде, что делает его сегментации: вместо

if (tree[idx] == '1') { 
    idx += 2; 
    return new HuffmanNode(tree[idx - 1]); 
} 

вы должны иметь

if (tree[idx] == '1') { 
    ++idx; 
    return new HuffmanNode(tree[idx]); 
} 

Другой 1 является добавляется к индексу во втором блоке:

idx++; 
HuffmanNode* leftChild = decodeTree(tree, idx); 
idx++; 
HuffmanNode* rightChild = decodeTree(tree, idx); 

Также подумайте о том, чтобы сделать что-то похожее на пример, с которым вы связались: передать ссылку на итератор строки (или istringstream или какой-либо другой поток) и не передавать индекс: HuffmanNode* HuffmanTree::decodeTree(std::string::const_iterator &tree).

Кроме того, вам не нужно делать проверки, такие как if (idx != tree.length() - 1), если дерево хорошо сформировано. Вы все еще можете сделать это в начале функции, чтобы проверить наличие ошибок на вашем входе, а также проверить, что текущий символ равен '0' или '1'.

+0

Что значит, если он хорошо сформирован? Он должен иметь какой-то базовый случай, не перестает ли он вызывать функцию и, возможно, выходит за пределы строки? Я попытался использовать итератор, но у меня была такая же проблема - я не знал, когда закончился входной поток, и закончил ли я чтение в самом дереве. –

+0

@TaylorBishop Нет, если в реализации нет ошибок, а закодированная строка верна, этот алгоритм не может читать за пределами строки. Посмотрите на сообщение, которое вы связали. Возможно иметь фактические данные в той же строке/массиве, что и дерево. Таким образом, вы можете начать декодировать данные из индекса, где вы закончите декодирование дерева. Все внутренние узлы в кодированном дереве отмечены 0, а листы - 1. После того, как вы прочтете узел, отмеченный знаком 1, вы не будете делать никаких рекурсивных вызовов. Это основной случай. – Kolmar