霍夫曼编码减缓了我的速度

时间:2013-12-03 00:22:15

标签: c# list encoding huffman-code

我认为我的代码中的这一部分让我感到沮丧。如何更改它以便更快。我必须阅读战争和片断。它适用于较小的样本,但不会在不少于3小时的情况下阅读战争。

while (note.Count > 1)
{
    // this is what I thing is taking the most time, because it loops through your note list, and builds a new list ordered by the node
    // and it gets worse the longer the list is.
    List<Node> orderedNodes = note.OrderBy(node => node.Frequency).ToList<Node>();

    if (orderedNodes.Count >= 2)
    {
        // Takes the  first two groups
        List<Node> taken = orderedNodes.Take(2).ToList<Node>();
        // Create greater node by combining the frequencies 
        Node parent = new Node()
        {
            Symbol = '*',
            Frequency = taken[0].Frequency + taken[1].Frequency,
            Left = taken[0],
            Right = taken[1]
        };
        note.Remove(taken[0]);
        note.Remove(taken[1]);
        note.Add(parent);
    }
    this.trunk = note.FirstOrDefault();
}

1 个答案:

答案 0 :(得分:3)

此代码具有最差的复杂度,如O(N *(N * 3 +(N * log N))) - 一目了然;确切的估计必须更糟。 实际上,它甚至可以在3个多小时内完成。 顺便说一句,它甚至完成了处理吗?

首先,通过使用以排序顺序维护节点的数据结构,以更有效的方式实现'note.OrderBy(node =&gt; node.Frequency)'的语义;或者想一想其他方法来防止在每一轮中重新排序整个列表,然后从中删除两个元素,然后添加另一个元素。

其次,在此代码中删除任何LINQ的痕迹。您对大型数据集进行了紧密循环,每轮都至少产生:

  • 5个隐式枚举器
  • 5个临时对象(列表和您的节点)

第三,确保'.Remove'和'.Add'采用常数或合理时间,但与物品数量不成线性比例。

然后,重新检查是否仍需要进一步优化。

开头的一些线索:

  • 考虑使用SortedSet保持您的项目有序(它在内部使用树)
  • 关注SortedSet的GetViewBetween进行搜索,http://msdn.microsoft.com/en-us/library/dd381801(v=vs.110).aspx
  • 想想也许你可以通过维护一个队列,并在其上移动逻辑窗口来实现这一点 - 例如您的确切问题是否类似于遍历树广度优先
  • 想想也许你可以完全避免做'。删除'和'.Add',而是预先分配所有节点,这样你的操作只会更新频率值并改变节点组织