В настоящее время у меня есть сортировка слиянием, которая сортирует список узлов в соответствии с целым числом в каждом узле, называемом «F» (So Node.F).
Однако у меня возникла необходимость использовать MergeSort для другого списка объектов — Entities. Однако я хочу отсортировать это в соответствии с целым числом в каждой сущности с именем «AmountEaten» (So Entity.AmountEaten).
Теперь вот моя проблема -> заставить класс MergeSort работать для всех объектов. Я уже заменил все ссылки на Node в рамках сортировки на «объект», но как разрешить настраиваемые критерии для сортировки? Есть ли способ предоставить его в качестве параметра.
Если это не имеет смысла, в MergeSort я сравниваю два значения (например, Left.F ‹ Right.F). С универсальным объектом это не работает, потому что F не существует. Я хотел бы иметь возможность сравнивать что-либо внутри объекта, внутри моей сортировки (например, Left.AmountEaten ‹ Right.AmountEaten). Я не могу понять, как указать это как параметр. Я сразу подумал о делегатах, но я не уверен, как/правильно ли это.
Поскольку сортировка имеет дело со списками, а не с отдельными объектами, я не могу просто указать параметр F/AmountEaten, поскольку я хотел бы получить доступ к переменной, а не к значению.
Если вам нужна дополнительная информация/не понимаю, пожалуйста, спросите.
Кажется, я пришел к некоторому выводу, но не могли бы вы помочь мне заставить его работать?
Класс сортировки слиянием:
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();