利用优先级队列C ++优化霍夫曼树算法从O(n ^ 2)到O(n)

时间:2015-03-29 06:52:11

标签: c++ algorithm huffman-code

我已经获得了这个用于组织霍夫曼树的代码段。

// Build a Huffman tree from a collection of frequencies
template <typename E> HuffTree<E>*
buildHuff(HuffTree<E>** TreeArray, int count) {
    heap<HuffTree<E>*,minTreeComp>* forest = 
        new heap<HuffTree<E>*, minTreeComp>(TreeArray, count, count); 
    HuffTree<char> *temp1, *temp2, *temp3 = NULL;
    while (forest->size() > 1) {
        temp1 = forest->removefirst();   // Pull first two trees  
        temp2 = forest->removefirst();   //   off the list
        temp3 = new HuffTree<E>(temp1, temp2);
        forest->insert(temp3);  // Put the new tree back on list
        delete temp1;        // Must delete the remnants
        delete temp2;        //   of the trees we created
    }
    return temp3;
}

这是一个非常典型的实现(忽略了糟糕的模板化和明显的内存泄漏)。

我应该修改这个算法,以便使用优先级队列来操作O(n)而不是O(n ^ 2)。我不确定如何实现这一点,但我猜测的是:

template <typename E> 
HuffTree<E>* buildHuff(HuffTree<E>** TreeArray, int count) {
    PriorityQueue<HuffTree<E>*, MIN_SORT> forest(count);
    for(int i = 0; i < count; i++) {
        forest.enqueue(TreeArray[i], TreeArray[i]->weight());
    }

    HuffTree<E> *tree = NULL;
    HuffTree<E> *left, *right = NULL;
    while(forest.size() > 0) {
        left = forest.dequeue();
        if (tree) {
            right = tree;
        }
        else {
            right = forest.dequeue();
        }
        tree = new HuffTree<E>(left, right);
        delete left;
        delete right;
    }
    return tree;
}

但它没有用。

为了简洁起见,我没有包含引用的类,但它们的实现非常简单。我很感激任何建议,以帮助引导我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:2)

您的实现始终选择刚创建的树作为下一棵树的子项之一。这不正确。考虑(有序)频率:

1, 1, 1, 1, 3

前两个将组合以产生频率为2的节点,但正确的第二个节点将不包括该节点。


我不知道如何使用优先级队列来生成解O(n),因为优先级队列需要O(log n)来删除最小元素。 (它可以用O(n)构建,但不能用你的方式构建。)

如果您还要使用O(n log n)算法,那么首先对频率进行排序会更容易。不需要进行进一步的排序,因为生成的节点是以单调非递减频率产生的,因此不需要优先级队列来保持它们的排序。你需要的是(逐步)合并已排序的叶子和(在生成时排序)非叶子。