我目前有一个合并排序,它根据每个节点中名为“F”(So Node.F)的整数对节点列表进行排序。
但是,我想出了将MergeSort用于另一个对象列表的实体 - 实体。但是,我想根据每个实体中名为“AmountEaten”(So Entity.AmountEaten)的整数对此进行排序。
现在这就是我的问题 - >使MergeSort类适用于所有对象。我已经用“对象”替换了排序中对Node的所有引用,但是如何允许自定义条件进行排序?有没有办法将其作为参数提供。
如果没有意义,在MergeSort中,我比较两个值(例如,Left.F< Right.F)。对于通用对象,这不起作用,因为F不存在。我希望能够在我的Sort(例如Left.AmountEaten< Right.AmountEaten)中比较对象内的任何内容。我无法弄清楚如何将此作为参数。我立刻想到了代表,但我不确定如何/如果这是对的。
由于排序涉及列表而不是单个对象,我不能简单地给出F / AmountEaten的参数,因为我想访问变量,而不是值。
如果您需要更多细节/不明白,请询问。
似乎已经达成了某种形式的结论,但是你可以帮助我让它发挥作用吗?
MergeSort类:
static class MergeSort
{
public static IList<object> Sort(IList<object> input, Comparison<object> comparison /* Comparison is a delegate that works out the difference
* between 2 values - Same signature used by List<T>.Sort */)
{
List<object> Result = new List<object>();
Queue<object> Left = new Queue<object>(); //Switched from lists to queues because removing at index 0 is more efficient
Queue<object> Right = new Queue<object>();
//Dequeue() and Count() have a time complexity of O(1)
if (input.Count <= 1)
return input;
int midpoint = input.Count / 2;
for (int i = 0; i < midpoint; i++)
Left.Enqueue(input[i]);
for (int i = midpoint; i < input.Count; i++)
Right.Enqueue(input[i]);
Left = new Queue<object>(Sort(Left.ToList(), comparison)); //Recursion! :o
Right = new Queue<object>(Sort(Right.ToList(), comparison)); ; //This line and the one above split the list into smaller lists (left and right)
Result = Merge(Left, Right, comparison); //This joins the lists together
return Result;
}
private static List<object> Merge(Queue<object> Left, Queue<object> Right, Comparison<object> comparison)
{
int cmp = comparison(Left.Peek(), Right.Peek());
//If cmp is less than 0, left is less. If it is greater, left is greater
List<object> Result = new List<object>();
while (Left.Count /* O(1) operation */ > 0 && Right.Count > 0)
{
if (cmp < 0)
Result.Add(Left.Dequeue());
//Left.RemoveAt(0) - Using a list to remove at a certain point is inefficient
else
Result.Add(Right.Dequeue());
}
while (Left.Count > 0)
Result.Add(Left.Dequeue());
while (Right.Count > 0)
Result.Add(Right.Dequeue());
return Result;
}
}
}
用法:的
Entities = MergeSort.Sort(Entities, (p, q) => p.F.CompareTo(q.F)).ToList();
答案 0 :(得分:1)
通常,最佳签名与List<T>.Sort(...)
使用的签名类似:
static void MergeSort<T>(IList<T> coll, Comparison<T> comparison)
{
...
// < 0 coll[i] < coll[j], == 0 coll[i] == coll[j], > 0 coll[i] > coll[j]
int cmp = comparison(coll[i], coll[j]);
...
}
使用:
MergeSort(coll, (p, q) => p.F.CompareTo(q.F));
请注意,如果F
是整数,您通常会看到比较:(p, q) => p.F - q.F
。这是有效的,因为如果p.F > q.F
然后p.F - q.F > 0
等等。
另一个可能的变体是LINQ OrderBy(...)
通常,最佳签名与List<T>.Sort(...)
使用的签名类似:
static void MergeSort<T, TKey>(IList<T> coll, Func<T, TKey> selector)
{
var comparer = Comparer<Tkey>.Default;
...
// < 0 coll[i] < coll[j], == 0 coll[i] == coll[j], > 0 coll[i] > coll[j]
int cmp = comparer(selector(coll[i]), selector(coll[j]));
...
}
使用:
MergeSort(coll, p => p.F);
这里我们向委托方法传递一个能够返回“排序键”的委托,如p => p.F
。它有点慢,使用起来比较困难(但它可能在LINQ中使用,因为它更类似于SQL中的内容)