在C#
的单个列表中对N个深度项进行排序。每个项目本身都有N个深度列表。该模型如下所示。
TestModel model = new TestModel
{
Name = "Model",
Nested = new List<TestModel>
{
new TestModel {
Name = "T1"
},
new TestModel {
Name = "T2"
},
new TestModel {
Name = "T3"
},
new TestModel {
Name = "T4-Nested01",
Nested = new List<TestModel> {
new TestModel {
Name = "T4-Nested01-T1",
},
new TestModel {
Name = "T4-Nested01-T2-Nested02",
Nested = new List<TestModel> {
new TestModel {
Name = "T4-Nested01-T2-Nested02-T1-Nested03",
Nested = new List<TestModel> {
new TestModel {
Name = "T4-Nested01-T2-Nested02-T1-Nested03-T1"
},
new TestModel {
Name = "T4-Nested01-T2-Nested02-T1-Nested03-T2"
},
new TestModel {
Name = "T4-Nested01-T2-Nested02-T1-Nested03-T3"
}
}
},
new TestModel {
Name = "T4-Nested01-T2-Nested02-T2"
},
new TestModel {
Name = "T4-Nested01-T2-Nested02-T3"
}
}
},
new TestModel {
Name = "Nested01-T2",
},
new TestModel {
Name = "Nested01-T3"
}
}
}
}
};
// model looks like this.
// ㄴ Name = "Model"
// ㄴ Nested Count 4
// ㄴ [0] TestModel T1
// ㄴ [1] TestModel T2
// ㄴ [2] TestModel T3
// ㄴ [3] TestModel T4
// ㄴ Name = "T4-Nested01"
// ㄴ Nested Count 4
// ㄴ [0] TestModel T4-Nested01-T1
// ㄴ [1] TestModel T4-Nested01-T2
// ㄴ Name = "T4-Nested01-T2-Nested02"
// ㄴ Nested Count 3
// [0] TestModel T4-Nested01-T2-Nested02-T1
// ㄴ Name = "T4-Nested01-T2-Nested02-T1-Nested03"
// ㄴ Nested Count 3
// [0] TestModel T4-Nested01-T2-Nested02-T1-Nested03-T1
// [1] TestModel T4-Nested01-T2-Nested02-T1-Nested03-T2
// [2] TestModel T4-Nested01-T2-Nested02-T1-Nested03-T3
// [1] TestModel T4-Nested01-T2-Nested02-T2
// [2] TestModel T4-Nested01-T2-Nested02-T3
// ㄴ [2] TestModel
// ㄴ [3] TestModel
单个列表,以便通过排序列表中的某些属性更轻松地搜索特定元素。我已经有了一个递归算法来实现这个目标。但我想使用非递归解决方案。
给我一个想法就足够了,或者如果你可以为我调整一个替代算法,那么也会非常感激。
答案 0 :(得分:5)
当您使用递归来迭代图形时,您似乎没有使用任何数据结构来执行遍历,但实际上您正在使用隐式/固有数据结构:Stack。因此,在没有递归的情况下执行相同类型的遍历,就需要堆栈。
在C#中你可以使用Stack,&#39; yield return&#39;关键字和委托,用于创建类似linq的扩展方法,该方法将以非常方便和可重用的方式执行此图遍历。下面是一个实现的概要:
public static IEnumerable<T> Flatten<T>(this T root, Func<T, IEnumerable<T>> selector)
{
var stack = new Stack<T>();
stack.Push(root);
while(stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach(var child in selector(current))
{
stack.Push(child);
}
}
}
你可以像这样使用它:
foreach(var item in model.Flatten(t=>t.Nested))
{
Console.WriteLine(item.Name);
}
你需要添加一些空检查,并且可选地检查以防止无限循环(如果图中的子项包含祖先,此算法将陷入无限循环,而递归算法将堆栈溢出)
这种类型的图遍历被称为“深度优先”&#39;。您可以实施“广度优先”&#39;只需将堆栈换成队列即可获得版本。