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);
}