C# 如何在不使用递归c的情况下遍历此树结构#
这段代码将循环数据保存在数据库中,但我遇到了性能问题,因为数据太大,它会保存大量记录,在这种情况下,递归会对内存造成非常大的负载,因此我需要一个递归的替代解决方案,因为这是一个n元树C# 如何在不使用递归c的情况下遍历此树结构#,c#,performance,tree,recursive-datastructures,C#,Performance,Tree,Recursive Datastructures,这段代码将循环数据保存在数据库中,但我遇到了性能问题,因为数据太大,它会保存大量记录,在这种情况下,递归会对内存造成非常大的负载,因此我需要一个递归的替代解决方案,因为这是一个n元树 private void ProcessLoops(LoopContainer parent, InboundLoop parentLoop) { foreach (var segment in parent.Segments) { if (s
private void ProcessLoops(LoopContainer parent, InboundLoop parentLoop)
{
foreach (var segment in parent.Segments)
{
if (segment is Loop)
{
var segmentLoop = segment as Loop;
var inboundLoop = new InboundLoop()
{
Inbound834RegisterId = RegisterId,
InboundSTId = InboundST.InboundSTId,
LoopName = segmentLoop.Specification.Name,
LoopNumber = segmentLoop.Specification.LoopId,
Sequence = _loopSequence++
};
if (parentLoop == null)
{
inboundLoop.InboundLoopId = InboundLoopService.Instance.AddInboundLoop(inboundLoop);
}
else
{
inboundLoop.ParentLoopId = parentLoop.InboundLoopId;
inboundLoop.InboundLoopId = InboundLoopService.Instance.AddInboundLoop(inboundLoop);
}
ProcessLoops(segmentLoop, inboundLoop);
}
}
}
每个递归都可以设置为循环。
对于深度搜索,您可以:
var nodeQueue = new Queue<Node>();
nodeQueue.Add(Tree.Root);
while (!nodeQueue.Empty())
{
var item = nodeQueue.Pop();
foreach(Node child in item.Children)
{
nodeQueue.Add(child);
}
db.Add(item.Data);
}
var length = Tree.Count;
var depth = Tree.Depth;
var maxLength = Power(2,depth)-1
for (var i=0; i<maxLength; i++)
{
db.Add(Tree.GetByNumber(i));
}
var nodeQueue=new Queue();
nodeQueue.Add(Tree.Root);
而(!nodeQueue.Empty())
{
var item=nodeQueue.Pop();
foreach(item.Children中的节点子节点)
{
nodeQueue.Add(子节点);
}
db.Add(项目数据);
}
另一种方法,需要更多时间,即计算树中项目的最大数量(我假设它可能不平衡)
var nodeQueue = new Queue<Node>();
nodeQueue.Add(Tree.Root);
while (!nodeQueue.Empty())
{
var item = nodeQueue.Pop();
foreach(Node child in item.Children)
{
nodeQueue.Add(child);
}
db.Add(item.Data);
}
var length = Tree.Count;
var depth = Tree.Depth;
var maxLength = Power(2,depth)-1
for (var i=0; i<maxLength; i++)
{
db.Add(Tree.GetByNumber(i));
}
var length=Tree.Count;
var depth=Tree.depth;
var maxLength=功率(2,深度)-1
对于(var i=0;i公共类节点信息
{
公共对象节点{get;set;}
公共队列属性被访问{get;set;}
}
公共静态类类型扩展
{
公共静态bool IsComplex(此类型)
{
return!type.IsValueType&&type!=typeof(字符串);
}
公共静态布尔IsCollection(此类型)
{
var collectionTypeName=typeof(ICollection).Name;
返回类型.Name==collectionTypeName | | type.GetInterface(typeof(ICollection).Name)!=null;
}
}
公共静态void遍历对象树(对象数据)
{
var currentNode=数据;
var currentNodeProperties=新队列(data.GetType().GetProperties());
var nodeTracker=新队列();
while(currentNodeProperties.Count!=0 | | nodeTracker.Count!=0)
{
如果(currentNodeProperties.Count==0&&nodeTracker.Count!=0)
{
var currentNodeInfo=nodeTracker.Dequeue();
currentNode=currentNodeInfo.Node;
currentNodeProperties=currentNodeInfo.PropertiesToBeVisited;
继续;
}
var currentNodeProperty=currentNodeProperties.Dequeue();
var currentNodePropertyType=currentNodeProperty.PropertyType;
if(currentNodePropertyType.IsComplex())
{
var value=currentNode?.GetType().GetProperty(currentNodeProperty.Name)
?.GetValue(currentNode,null);
if(值!=null)
{
对象节点;
if(currentNodePropertyType.IsCollection())
{
var elementType=currentNodePropertyType.IsArray
?value.GetType().GetElementType()
:value.GetType().GetGenericArguments()[0];
node=Activator.CreateInstance(elementType??抛出新的InvalidOperationException());
}
其他的
{
节点=值;
}
nodeTracker.Enqueue(新节点信息
{
节点=当前节点,
PropertiesToBeVisited=currentNodeProperties
});
currentNode=节点;
currentNodeProperties=新队列(node.GetType().GetProperties());
Console.WriteLine(currentNodeProperty.Name);
继续;
}
}
Console.WriteLine(currentNodeProperty.Name);
}
}
这将完成任务!!我创建了一种方法,可以将项目按递归处理的顺序展开,而不使用递归。由于这是一种通用的扩展方法,它可以用于任何事情。例如,您可以将T
作为操作,以便您可以随时处理它们xtension方法:
公共静态类EnumerableExtensions
{
公共静态列表到递归OrderList(此IEnumerable集合、表达式childCollection)
{
var resultList=新列表();
var currentItems=新队列(collection.Select(i=>(0,i,0));
var-depthItemCounter=0;
var previousItemDepth=0;
var childProperty=(PropertyInfo)((MemberExpression)childCollection.Body.Member;
而(currentItems.Count>0)
{
var currentItem=currentItems.Dequeue();
//当深度改变时,重置此深度处项目数的计数器。
如果(currentItem.Depth!=previousItemDepth)depthItemCounter=0;
var resultIndex=currentItem.Index+depthItemCounter++;
resultList.Insert(resultIndex,currentItem.Item);
var childItems=childProperty.GetValue(currentItem.Item)作为IEnumerable??Enumerable.Empty();
foreach(childItems中的var childItem)
{
currentItems.Enqueue((resultIndex+1,childItem,currentItem.Depth+1));
}
previousItemDepth=currentItem.Depth;
}
返回结果列表;
}
}
下面是一个如何使用它的示例。像这样的结构将被展平
- A
- B
- C
- D
- E
- F
- G
- H
- 我
- J
- K
- L
- M
- N
- O
- P