我正在尝试创建一个递归函数,该递归函数遍历数字字典,然后输出每个节点的遍历路径。
数据结构看起来像这样:
var tree = new Dictionary<int, List<int>>()
{
{888, new List<int>() {44}},
{ 44, new List<int>() {183, 275, 100, 216}},
{100, new List<int>() {299, 400}},
{299, new List<int>() {504}},
{216, new List<int>() {33}}
};
所以代表数据结构的树形结构看起来像这样
888
/ \
44 (many other nodes and subnodes)
/ / \ \
183 275 100 216
/ \ \
299 400 33
/
504
我想返回一个列表列表,输出类似这样的内容
[888, 44, 183]
[888, 44, 275]
[888, 44, 100, 299, 504]
[888, 44, 100, 400]
[888, 44, 216, 33]
到目前为止,这可能是不正确的。我可以成功获得一些想要的结果。我认为问题在于,这并不是在所有子节点都已被访问的情况下删除具有子节点的节点。
public List<int[]> FindPaths(int currentNode, Dictionary<int, List<int>> tree, List<int> temp, List<int> visitedNodes)
{
if (tree.ContainsKey(currentNode))
{
if (!visitedNodes.Contains(currentNode))
{
visitedNodes.Add(currentNode);
}
foreach (var node in tree[currentNode])
{
visitedNodes.Add(node);
temp.Add(node);
// call method again with new values
FindPaths(node, tree, temp, visitedNodes);
}
// if node has no children left and is not a leaf node
// do something here?
}
else // we have reached a leaf node
{
paths.Add(temp.ToArray());
temp.RemoveAt(temp.Count - 1);
return paths;
}
return paths;
}
调用函数
paths = new List<int[]>();
var temp = new List<int>();
var vistedNodes = new List<int>();
var result = FindPaths(888, tree, temp, vistedNodes);
有人可以帮助我获得所需的输出吗?如果可能的话,我想递归地完成这项工作
答案 0 :(得分:0)
尝试这个:
public List<List<int>> FindPaths(int currentNode, Dictionary<int,List<int>> tree)
{
List<List<int>> paths = new List<List<int>>();
if(tree.ContainsKey(currentNode))
{
foreach(var node in tree[currentNode])
{
var subPaths = FindPaths(node,tree);
foreach(var subPath in subPaths)
{
subPath.Insert(0,currentNode);
paths.Add(subPath);
}
}
}
else
{
paths.Add(new List<int>(){currentNode});
}
return paths;
}
请注意,这是假设您没有圆形路径(A-> B-> C-> A)。如果词典中包含一个,您将陷入循环中。如果可能的话,您必须跟踪访问的节点并避免对其进行重新处理。
答案 1 :(得分:0)
类似于您的方法,此解决方案是在访问时继续添加节点,在该节点不存在任何键时收集列表,并在迭代结束时删除该元素。
void findPaths(int root, Dictionary<int,List<int>> tree,List<List<int>> pathList, List<int> visitedNodes)
{
visitedNodes.Add(root);
if(tree.ContainsKey(root))
{
foreach(int v in tree[root])
{
findPaths(v,tree,pathList,visitedNodes);
visitedNodes.RemoveAt(visitedNodes.Count - 1);
}
}
else
{
pathList.Add(new List<int>(visitedNodes));
}
}
答案 2 :(得分:0)
使用这种方法很容易解决
//Just some helper method
public static IEnumerable<TKey[]> GetPaths<TKey, TDictImpl>(this IDictionary<TKey, TDictImpl> dict) where TDictImpl : IEnumerable<TKey>
{
var watchlist = new List<TKey>();
var outlist = new List<List<TKey>>();
GetPaths(dict, dict.Keys.First(), watchlist, outlist, new List<TKey> { dict.Keys.First() });
return outlist.Select((l) => l.ToArray());
}
private static void GetPaths<TKey, TDictImpl>(this IDictionary<TKey, TDictImpl> dict, TKey parent, List<TKey> watchlist, List<List<TKey>> outlist, List<TKey> current) where TDictImpl : IEnumerable<TKey>
{
//Try to get our child from the dict
if (!dict.TryGetValue(parent, out TDictImpl subs))
{
//No child found, no further navigation needs to be done
return;
}
foreach (var it in subs)
{
//Simple check to make sure we do not end in some endless loop
if (watchlist.Contains(it))
{
throw new FormatException($"The key {it.ToString()} was attempted to be traversed a second time in {parent.ToString()}.");
}
else
{
watchlist.Add(it);
}
//Add everything to our outlist
var tmp = current.Concat(new TKey[] { it }).ToList();
outlist.Add(tmp);
//Proceed with possible childnodes
GetPaths(dict, it, watchlist, outlist, tmp);
}
}
为
生成var tree = new Dictionary<int, List<int>>()
{
{888, new List<int>() {44}},
{ 44, new List<int>() {183, 275, 100, 216}},
{100, new List<int>() {299, 400}},
{299, new List<int>() {504}},
{216, new List<int>() {33}}
};
var res = Random.GetPaths(tree);
以下输出
[888, 44]
[888, 44, 183]
[888, 44, 275]
[888, 44, 100]
[888, 44, 100, 299]
[888, 44, 100, 299, 504]
[888, 44, 100, 400]
[888, 44, 216]
[888, 44, 216, 33]