在内存中存储部分共享字符串集合的最有效方法

时间:2012-10-15 17:12:14

标签: c# arrays string memory recursion

我有一个递归的C#应用​​程序,它遍历一个树,只要最后一个节点等于X,就需要维护链中所有节点的历史记录。

例如,我正在搜索下面的MATCH一词

Root
 |
 |-Node1
 |   |-Sub1
 |   |-MATCH
 |
 |-Node2
 |   |-Node22
 |   |-Node33
 |   |   |-MATCH
 |   |-Node3
 |
 |-Node3
 |   |-Node88
     |-MATCH

注意Node3是Node2的兄弟。我的目标是确定根与遇到MATCH的每条路径之间的父子关系。这意味着生成以下输出:

   Root -> Node1 -> MATCH
   Root -> Node2 -> Node33 -> MATCH
   Root -> Node2 -> Node3  -> MATCH
   Root -> Node3 -> MATCH

对此进行编码的正确方法是什么?

我立即看到,任何跟踪深路径或长路径的尝试都会导致大部分内存被用于跟踪没有值的路径。唯一有价值的路径是上面列出的路径,其中找到匹配

我的目标是在Azure Table或Blob存储上实现这一点...每个IO查询批量为100行,在每个级别的heiarchy中最多可查询20,000行。

我确信此前已经完成,但不知道它会被称为什么..

问题

我应该如何引用内存中的字符串以便消耗最少的RAM?

示例答案:

使用带有ref参数的结构......或......

Struct MyMemoryData
{
    public string PreviousNode {get;set;}
    public string NodeName {get;set;}
}

void MyRecursion(MyMemoryData searchStack, List<string> nodesToQuery)
{
    foreach(var str in nodesToQuery)
    {
        var newToDoList = GetChildNodes(str);

        searchStack.PreviousNode = searchStack.CurentNode;
        searchStack.CurrentNode = str;
        MyRecursion(searchStack, newToDoList);
    }
}

或将ref保存到struct

 Struct MyMemoryData
    {
        public MyMemoryData PreviousNode {get;set;}  // this line was changed: Type is MyMemoryData
        public string NodeName {get;set;}
    }

    void MyRecursion(MyMemoryData searchStack, List<string> nodesToQuery)
    {
        foreach(var str in nodesToQuery)
        {
            var newToDoList = GetChildNodes(str);

            searchStack.PreviousNode = searchStack;  // this line was changed: Saving the object instead of the value
            searchStack.CurrentNode = str;
            MyRecursion(searchStack, newToDoList);
        }
    }

或者只是将它们保存在这样的列表中:

void MyRecursion(List<string> searchStack, List<string> nodesToQuery)
{
    foreach(var str in nodesToQuery)
    {
        var newToDoList = GetChildNodes(str);

        searchStack.Add(str);
        MyRecursion(searchStack, newToDoList);
    }
}

2 个答案:

答案 0 :(得分:0)

您打算提供多少级别?堆栈的大小应该受树的深度影响,而不是每个级别的项目数。

void MyRecursion(Stack<string> searchStack, List<string> nodesToQuery)
{
    foreach(var str in nodesToQuery)
    {
        var newToDoList = GetChildNodes(str);

        searchStack.Push(str);
        MyRecursion(searchStack, newToDoList);
        searchStack.Pop(); // make sure to get pop off the current once you are no longer on this level
    }
}
编辑:老实说,我认为您可能想要考虑一种迭代方法。你的大部分内存将被newToDoList存储在每个递归级别。如果你可以顺序遍历树(想想XmlReader只是向前)并保持一个堆栈,你可能会更好。

答案 1 :(得分:0)

听起来你正在寻找地图缩减算法。

其他人提到MapReduce是一个潜在的选择;有些人一直致力于在Azure中使用它。

有许多文章/算法,例如this link,可以帮助您制作自己的文章/算法。