算法原理看其他文章
使用UIElements 编写的节点编辑器:https://gitee.com/weifen/node-editor
基本算法:
public static class BFSHelper
{
public static T[] BFSForEach<T>(this List<T> array, T start, Func<T, T, bool> filter)
{
return BFSForEach(array.ToArray(), start, filter);
}
public static T[] BFSForEach<T>(this T[] array, T start, Func<T, T, bool> filter)
{
var count = array.Length;
List<T> results = new List<T>();
Queue<T> queue = new Queue<T>();
HashSet<T> visited = new HashSet<T>();
queue.Enqueue(start);
visited.Add(start);
while (queue.Count != 0)
{
var _ = queue.Dequeue();
results.Add(_);
for (var i = 0; i < count; i++)
{
var __ = array[i];
if (!visited.Contains(__) && filter(_, __))
{
queue.Enqueue(__);
visited.Add(__);
}
}
}
return results.ToArray();
}
}
算法扩展到树上。对节点树遍历
当进入一个节点的时候,访问的前面节点结果必然是已运算结果
所以需要从左边开始执行节点,下一个节点才可以获得前面所有节点运算结果
public interface INode
{
INode[] GetLefts();
INode[] GetRights();
}
public static class TreeHelper
{
public static T[] ForEach<T>(this T start)where T :INode
{
Dictionary<T, bool> visited = new Dictionary<T, bool>();
Queue<T> queue = new Queue<T>();
List<T> nodes = new List<T>();
queue.Enqueue(start);
visited.Add(start, false);
while (queue.Count > 0)
{
var _ = queue.Dequeue();
int count = 0;
foreach (T __ in _.GetLefts())
{
if (!visited.ContainsKey(__))
{
count++;
queue.Enqueue(__);
visited.Add(__, false);
}
}
if (visited.ContainsKey(_) && count == 0)
{
if(!visited[_])
{
visited[_] = true;
nodes.Add(_);
}
foreach (T __ in _.GetRights())
{
queue.Enqueue(__);
if (!visited.ContainsKey(__))
{
visited.Add(__, false);
}
}
}
}
return nodes.ToArray();
}
}
遍历demo:
先断开根节点的连接,获得N棵需要遍历的树
var rootNode = runtimeDict[tree.root.guid];
List<RuntimeNode> list = new List<RuntimeNode>();
foreach (var port in rootNode.outputNodes)
{
list.Add(port.input);
}
rootNode.Clear();
foreach (var item in list)
{
runtimeNodes.Add(item.ForEach());
}
简单遍历
public void ForEach(Func<RuntimeNode,bool> func)
{
foreach (var nodes in runtimeNodes)
{
Debug.LogError(">>>>>");
foreach (var node in nodes)
{
if (func?.Invoke(node) ?? false)
break;
}
}
}
条件节点遍历测试