Arrays 算法:基于约束对数组中的对象排序
我有一千个类型为Arrays 算法:基于约束对数组中的对象排序,arrays,algorithm,sorting,Arrays,Algorithm,Sorting,我有一千个类型为MyClass class MyClass{ array<MyClass> objectsBehind; Boolean large; } 在第一个序列中,我将三个大对象分组在一起,而不是在第二个示例中分散 我想不出一个好办法。有什么想法吗?这很容易做到 首先,要在每个此类对象的objectsBehind数组中的所有对象之前对对象进行排序,可以使用 拓扑排序将在每次主迭代中“同时”将多个元素放入输出集合 您可以按“大”属性对这些对象进行排序,以便所
MyClass
class MyClass{
array<MyClass> objectsBehind;
Boolean large;
}
在第一个序列中,我将三个大对象分组在一起,而不是在第二个示例中分散
我想不出一个好办法。有什么想法吗?这很容易做到 首先,要在每个此类对象的
objectsBehind
数组中的所有对象之前对对象进行排序,可以使用
拓扑排序将在每次主迭代中“同时”将多个元素放入输出集合
您可以按“大”属性对这些对象进行排序,以便所有大对象排在第一位,然后是所有非大对象。您可能希望在此添加另一个排序条件,以便可以依赖大型对象内部和非大型对象内部的已知顺序
基本上,以下是拓扑排序的工作原理(我所学的):
objectsBehind
属性中内置了此项)我有点困惑。在您的示例中,看起来您可以通过
large
值将索引任意分配给要分组的值。如果情况并非如此,您能否举例说明如何根据large
对已排序的数据进行分组?创建两个集合,一个是large=true
并对其排序,另一个是large=false
并对其排序。否则,任何两个large=true
元素相邻的事实只是第一个排序条件的属性。我想不出一个有意义的方法来包含large=true
元素,让它们按顺序排列,并且不违反您的第一个标准。1000
对于许多平台来说是一个非常小的数字,以至于一个有序的序列在任何情况下都可能是不相关的。但标准库为您提供了模板化容器,您甚至可以在其中使用自己的谓词并重载给定的运算符,以根据给定的字段保持数据结构有序。快速查看wikipedia条目表明,拓扑排序确实可能正是我所需要的。我会试一试,稍后再来。非常感谢。太神了非常感谢你的努力。非常好的回答让我知道(在这里或lasse@vkarlsen.no)如果您对代码或方法有疑问。
array[45].large = false; array[46].large = true, array[47].large = true, array[48].large = true, array[49].large = false;
array[45].large = true; array[46].large = false, array[47].large = true, array[48].large = false, array[49].large = true;
const int OBJECT_NUM = 10;
void Main()
{
Random r = new Random(12345);
var objects = new List<MyClass>();
for (int index = 1; index <= OBJECT_NUM; index++)
{
var mc = new MyClass { Id = index, IsLarge = (r.Next(100) < 50) };
objects.Add(mc);
}
for (int index = 0; index < objects.Count; index++)
{
var temp = new List<MyClass>();
for (int index2 = index + 1; index2 < objects.Count; index2++)
if (r.Next(100) < 10 && index2 != index)
temp.Add(objects[index2]);
objects[index].ObjectsBehind = temp.ToArray();
}
objects.Select(o => o.ToString()).Dump("unsorted");
objects = LargeTopoSort(objects).ToList();
objects.Select(o => o.ToString()).Dump("sorted");
}
public static IEnumerable<MyClass> LargeTopoSort(IEnumerable<MyClass> input)
{
var inboundLinkCount = new Dictionary<MyClass, int>();
var inputArray = input.ToArray();
// the hash set initially contains all the objects
// after the first loop here, it will only contain objects
// that has no inbound links, they basically have no objects
// that comes before them, so they are "first"
var objectsWithNoInboundLinks = new HashSet<MyClass>(inputArray);
foreach (var source in inputArray)
{
int existingInboundLinkCount;
foreach (var target in source.ObjectsBehind)
{
// now increase the number of inbound links for each target
if (!inboundLinkCount.TryGetValue(target, out existingInboundLinkCount))
existingInboundLinkCount = 0;
existingInboundLinkCount += 1;
inboundLinkCount[target] = existingInboundLinkCount;
// and remove it from the hash set since it now has at least 1 inbound link
objectsWithNoInboundLinks.Remove(target);
}
}
while (objectsWithNoInboundLinks.Count > 0)
{
// all the objects in the hash set can now be dumped to the output
// collection "at the same time", but let's order them first
var orderedObjects =
(from mc in objectsWithNoInboundLinks
orderby mc.IsLarge descending, mc.Id
select mc).ToArray();
foreach (var mc in orderedObjects)
yield return mc;
// prepare for next "block" by clearing the hash set
// and removing all links from the objects we just output
objectsWithNoInboundLinks.Clear();
foreach (var source in orderedObjects)
{
foreach (var target in source.ObjectsBehind)
{
if (--inboundLinkCount[target] == 0)
{
// we removed the last inbound link to an object
// so add it to the hash set so that we can output it
objectsWithNoInboundLinks.Add(target);
}
}
}
}
}
public class MyClass
{
public int Id; // for debugging in this example
public MyClass[] ObjectsBehind;
public bool IsLarge;
public override string ToString()
{
return string.Format("{0} [{1}] -> {2}", Id, IsLarge ? "LARGE" : "small", string.Join(", ", ObjectsBehind.Select(o => o.Id)));
}
}
unsorted
1 [LARGE] -> 5
2 [LARGE] ->
3 [small] ->
4 [small] -> 7
5 [small] ->
6 [small] ->
7 [LARGE] ->
8 [small] ->
9 [LARGE] -> 10
10 [small] ->
sorted
1 [LARGE] -> 5
2 [LARGE] ->
9 [LARGE] -> 10
3 [small] ->
4 [small] -> 7
6 [small] ->
8 [small] ->
7 [LARGE] ->
5 [small] ->
10 [small] ->