Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 函数列表变量不';t返回递归变量的当前状态_C#_Recursion_Unity3d - Fatal编程技术网

C# 函数列表变量不';t返回递归变量的当前状态

C# 函数列表变量不';t返回递归变量的当前状态,c#,recursion,unity3d,C#,Recursion,Unity3d,我使用的是图形数据结构,有一个递归函数,通过计算根节点的父节点来计算节点的深度 我还需要处理一些其他问题,但目前我的主要问题是存储递归字典参数的当前值,该参数存储路径分支 using System; using System.Collections.Generic; using System.Linq; public class Node { public string name; public int ID; public int maxDepth; publ

我使用的是图形数据结构,有一个递归函数,通过计算根节点的父节点来计算节点的深度

我还需要处理一些其他问题,但目前我的主要问题是存储递归字典参数的当前值,该参数存储路径分支

using System;
using System.Collections.Generic;
using System.Linq;

public class Node {
    public string name;
    public int ID;
    public int maxDepth;
    public readonly List<Node> Dependencies = new List<Node>();
    public readonly List<Node> Children = new List<Node>();

    public bool isOrphan {
        get {
            return Dependencies.Count == 0;
        }
    }

    public bool isParent {
        get {
            return Children.Count != 0;
        }
    }
}

public class test {
    private static readonly List<Node> nodes = new List<Node>(); 
    public static void Main() {
        Node A = new Node() {
            name = "A",
            ID = 1
        };

        Node B = new Node() {
            name = "B",
            ID = 2
        };

        Node C = new Node() {
            name = "C",
            ID = 3
        };

        Node D = new Node() {
            name = "D",
            ID = 4
        };

        Node E = new Node() {
            name = "E",
            ID = 5
        };

        Node F = new Node() {
            name = "F",
            ID = 6
        };

        Node G = new Node() {
            name = "G",
            ID = 7
        };

        nodes.Add(A);
        nodes.Add(B);
        nodes.Add(C);
        nodes.Add(D);
        nodes.Add(E);
        nodes.Add(F);
        nodes.Add(G);

        A.Children.Add(B);
        A.Children.Add(G);
        B.Children.Add(C);
        B.Children.Add(D);
        C.Children.Add(D);
        D.Children.Add(E);
        E.Children.Add(F);

        B.Dependencies.Add(A);
        C.Dependencies.Add(B);
        D.Dependencies.Add(B);
        D.Dependencies.Add(C);
        E.Dependencies.Add(D);
        E.Dependencies.Add(G);
        F.Dependencies.Add(E);
        G.Dependencies.Add(A);

        foreach (Node n in nodes) {
            n.maxDepth = getMaxNodeDepth(n);
        }

        Console.ReadLine();
    }

    private static int getMaxNodeDepth(Node n, string listIndex = "base",
                    Dictionary<string, List<int>> paths = null) {
        bool firstIteration = false;

        if (paths == null) {
            firstIteration = true;
            listIndex = n.name.Replace(" ", "-");
            paths = new Dictionary<string, List<int>> {
                {listIndex, new List<int>(0)} 
            };
        }

        // Prevent the starting node from being added to the path
        if (!paths[listIndex].Contains(n.ID) && !firstIteration)
            paths[listIndex].Add(n.ID);

        // This variable should take the CURRENT path and store it; 
        // not the value after all the recursion has completed.
        // Right now, the current path is affected by the recursions, somehow...
        List<int> currentPath = new List<int>(paths[listIndex]);

        foreach (Node parent in n.Dependencies) {
            if (n.Dependencies.Count >= 2) {
                listIndex = parent.name;
                paths.Add(listIndex, currentPath);
            }
            getMaxNodeDepth(parent, listIndex, paths);
        }

        // Print out branches
        if (firstIteration) {
            string list = n.name + "\n";
            int listNumber = 1;
            foreach (List<int> iList in paths.Values) {
                list += string.Format("Branch#{0} -- ", paths.Keys.ElementAt(listNumber - 1));
                int total = 0;
                foreach (int i in iList) {
                    list += string.Format("{0}, ", nodes.First(x => x.ID == i).name);
                    total++;
                }
                listNumber++;
                list += string.Format(" -- ({0})\n", total);
            }
            Console.WriteLine(list);
        }

        // Order all paths by length, return the highest count
        // This is to be used to space out the hierarchy properly
        return paths.Values.OrderByDescending(path => path.Count).First().Count;
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
公共类节点{
公共字符串名称;
公共int ID;
公共int最大深度;
公共只读列表依赖项=新列表();
public readonly List Children=new List();
公共图书馆{
得到{
返回依赖项。计数==0;
}
}
公共图书馆{
得到{
返回子项。计数!=0;
}
}
}
公开课考试{
私有静态只读列表节点=新列表();
公共静态void Main(){
节点A=新节点(){
name=“A”,
ID=1
};
节点B=新节点(){
name=“B”,
ID=2
};
节点C=新节点(){
name=“C”,
ID=3
};
节点D=新节点(){
name=“D”,
ID=4
};
节点E=新节点(){
name=“E”,
ID=5
};
节点F=新节点(){
name=“F”,
ID=6
};
节点G=新节点(){
name=“G”,
ID=7
};
节点。添加(A);
节点。添加(B);
节点。添加(C);
节点。添加(D);
节点。添加(E);
节点。添加(F);
节点。添加(G);
A.儿童。添加(B);
A.儿童。添加(G);
B.儿童。添加(C);
B.儿童。添加(D);
C.儿童。添加(D);
D.儿童。添加(E);
E.儿童。添加(F);
B.增加(A);
C.增加(B);
D.增加(B);
D.增加(C);
E.增加(D);
E.相关性。添加(G);
F.增加(E);
G.增加(A);
foreach(节点中的节点n){
n、 maxDepth=getMaxNodeDepth(n);
}
Console.ReadLine();
}
私有静态int getMaxNodeDepth(节点n,字符串listIndex=“base”,
字典路径=空){
bool firstIteration=false;
if(路径==null){
第一次迭代=真;
listIndex=n.name.Replace(“,“-”);
路径=新字典{
{listIndex,新列表(0)}
};
}
//阻止将起始节点添加到路径
如果(!paths[listIndex].包含(n.ID)&&!firstIteration)
路径[listIndex]。添加(n.ID);
//此变量应采用当前路径并存储它;
//不是所有递归完成后的值。
//现在,当前路径受到递归的影响,不知何故。。。
List currentPath=新列表(路径[listIndex]);
foreach(n.Dependencies中的节点父节点){
如果(n.Dependencies.Count>=2){
listIndex=parent.name;
添加(listIndex,currentPath);
}
getMaxNodeDepth(父级、列表索引、路径);
}
//打印分支
if(第一次迭代){
字符串列表=n.name+“\n”;
int listNumber=1;
foreach(在path.Values中列出iList){
list+=string.Format(“Branch#{0}--”,path.Keys.ElementAt(listNumber-1));
int-total=0;
foreach(iList中的int i){
list+=string.Format(“{0},”,nodes.First(x=>x.ID==i.name);
总计++;
}
listNumber++;
list+=string.Format(“--({0})\n”,总计);
}
控制台写入线(列表);
}
//按长度排序所有路径,返回最大计数
//这将用于正确分隔层次结构
返回path.Values.OrderByDescending(path=>path.Count).First().Count;
}
}
当foreach循环遇到一个具有多个父节点的节点时,它将创建一个新分支,并应使用节点的当前ID填充该分支

cd
\ /
B
|
A.
|
…

该怎么办 使用上面的示例,从A开始,它将首先迭代B,作为它的直接父级。然后它从B的父节点开始,它有两个,因此,它创建一个单独的分支,并用B及其子节点填充该分支(直到开始节点,这次是a)

究竟是什么 不知何故,当B完成了对C的迭代后,
parent D
轮询当前路径并返回
B,C
,它实际上应该是
B
,因为C是同级,而不是直接的子级或父级

大编辑 我附带的代码完全是开箱即用的,其中包含一个示例。您可以看到结果包含一些异常结果,例如

F
分支机构#G--E,D,G,A,-(4)

实际上应该是


G
分支机构#G--G,A,--(2)

将字典作为参数提供给方法时,不会复制字典的内容,只复制对字典的引用。 因此,改变一个递归分支中的字典也会改变另一个分支的字典。 要修复此问题,您可以在传递字典时自己显式复制字典:
getMaxNodeDepth(父级、列表索引、新字典(路径))

编辑:实际上这也不够,因为它将复制对内部列表的引用,而不是内部列表的内容,因此您需要一个更嵌套的克隆代码:

    private Dictionary<string, List<int>> clone(Dictionary<string, List<int>>  map)
    {
        Dictionary<string, List<int>> clone = new Dictionary<string,  List<int>>(map.Count);
        foreach (var pair in map)
        {
            clone[pair.Key] = new List<int>(pair.Value);
        }
        return clone;
    }

    //And then call it from your code:
    getMaxNodeDepth(parent, listIndex, clone(paths));
编辑:编辑以添加返回结果的解决方案
private int getMaxNodeDepth(Node n)
{
     if (n.Dependencies == null || n.Dependencies.Count == 0) return 1;
     return 1 + n.Dependencies.Max(parent => getMaxNodeDepth(parent));
}
    private List<Node> getMaxNodeDepth(Node n)
    {
        List<Node> path =
            n.GetSubFolders().Select(getMaxNodeDepth).OrderByDescending(p => p.Count).
            FirstOrDefault() ?? new List<Node>();
        path.Insert(0, n);
        return path;
    }
    private static List<List<Node>> getAllPaths(Node n)
    {
        if (n.Dependencies == null || n.Dependencies.Count == 0)
            return new List<List<Node>> { new List<Node> { n }};
        List<List<Node>> allPaths = n.Dependencies.SelectMany(getAllPaths).ToList();
        allPaths.ForEach(path => path.Insert(0, n));
        return allPaths;
    }

    private static int getMaxDepth(Node n)
    {
        return getAllPaths(n).Max(p => p.Count);
    }