哪种数据结构适合我的情况?

时间:2012-12-18 15:53:46

标签: c# optimization data-structures dictionary

首先,这可能是一个XY问题,对不起。

我正在从文件加载文件表并将其放入内存中的文件树中。树中的节点表示树中的目录/文件。目前,我每个节点使用两个数据结构,由于插入到集合中而导致明显的加载时间,并且由于重复字符串数据和引用每个节点两次而导致更高的内存使用量。树木被装载一次,之后不会发生变异。

每个节点都有一个用于访问已排序子节点的List和一个用于按名称访问子节点的Dictionary。由于性能原因,该列表被懒惰地排序。 SortedDictionary不符合我的使用要求,因为我需要将子节点放在没有子节点的节点之上,因此传递IComparer是不够的。当两个节点都有/没有子节点时,它们按字典顺序排序(OrdinalIgnoreCase)。

.net中是否有满足我需求的数据结构?

另外,是否有任何方法可以在插入字典时为密钥提供哈希值,以及稍后从字典中获取一部分桶(即:​​GetValuesByHash(int hashValue))相应键具有给定散列的所有值)?我正在读取的文件表已经包含整个文件路径的哈希值(适用于我正在做的另一件事),而且目前,字典只是无缘无故地重新计算它们。

我认为我可以通过定义我自己的自定义键来解决一个解决方案,其中包含{Hash,Node}和自定义比较器,但这看起来真的很难看,而且你无法获得共享相同节点的桶哈希值。如果有的话,那仍然会感觉使用错误的数据结构。

我已经使用Google搜索“c#dictionary get hash”以及其他一些查询,但此时我还没有看到任何类似的问题。

总体而言,寻找具有以下属性的数据结构(可能与字典相关):

  • ContainsKeyOfHash(),Get(hash):文件名哈希 - >文件输入描述符
  • ContainsKey(),Get(key):文件名 - >文件输入描述符
  • 添加(字符串fileName,条目条目,int hash = gethash(fileName))
  • 条目分类如下:

        m_children.Sort(
           (a, b) => {
              bool aHasChildren = a.HasChildren;
              bool bHasChildren = b.HasChildren;
              if (aHasChildren && !bHasChildren)
                 return 1;
              if (!aHasChildren && bHasChildren)
                 return -1;
              else
                 return -String.Compare(a.m_resourceName, b.m_resourceName, StringComparison.OrdinalIgnoreCase);
           }
        );
    
  • 可以按上述排序顺序检索所有子节点。目前,我有一个ChildrenSorted和ChildrenUnsorted属性。由于排序,ChildrenSorted属性可能会受到影响,而ChildrenUnsorted属性则不会。

我认为更糟糕的是,我的解决方案是编写自己的类字典类。我不必从字典中删除键,所以它应该不难。不过,我有点想避免这样做。

我的节点实施可在以下位置查看:http://pastie.org/5547925

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为您的解决方案已经非常好了。以下是一些想法:

  1. 对于既已排序又可通过密钥快速访问的集合,我只能想到树数据结构。您可能不希望每个项目分配一个对象的数据结构。可能你最好通过一种堆,所有项目都放在一个数组中。我认为你可以通过首先对所有孩子进行排序然后填充它们来非常有效地构建这种结构(就像你现在正在做的那样)。
  2. 您可以考虑将所有数据填充到单个此类树中。这样可以节省大多数每节点开销(比如本身有子对象的集合)。密钥将是节点的“路径”,以某种有效格式存储。它可以是"d1\d2\filename"string[]之类的路径。
  3. 点(2)将是RDBMS如何做到的。

答案 1 :(得分:0)

您只需将SortedDictionary lambda放入“IComparer:

即可使用Sort()
public class MyComparer : IComparer, IComparer<MyNode>
{
    public int Compare(object x, object y)
    {
        return Compare(x as MyNode, y as MyNode);
    }

    public int Compare(MyNode x, MyNode y)
    {
        if (ReferenceEquals(x, y))
        {
            return 0;
        }

        if (ReferenceEquals(x, null))
        {
            return -1;
        }

        if (ReferenceEquals(y, null))
        {
            return 1;
        }

        bool xHasChildren = x.HasChildren;
        bool yHasChildren = y.HasChildren;
        if (xHasChildren && !yHasChildren)
            return 1;
        if (!xHasChildren && yHasChildren)
            return -1;
        else
            return String.Compare(y.m_resourceName, x.m_resourceName, StringComparison.OrdinalIgnoreCase);
    }
}