Какая сортировка - это?

Это было бы верно в стандартной системе на 32 бита, но конечно, нет никаких гарантий, и Вы могли найти большую архитектуру, где это не верно. Например, распространенное заблуждение - то, что sizeof (интервал) на x86_64 был бы 8 (так как это - система на 64 бита, я предполагаю), который это не. На x86_64, sizeof (интервал) все еще 4, но sizeof (пусто*) равняется 8.

6
задан 11 revs, 2 users 98% 23 May 2017 в 12:19
поделиться

4 ответа

Пока это работает. Если и только если существует заказ, удовлетворяющий условиям, он его найдет. Пока не пробовал оптимизировать. Он работает в обратном порядке, отслеживая, какие элементы не могут быть добавлены предыдущей операцией.

Изменить: Я не могу отметить это как ответ, потому что я уже сильно пострадал от этого и у меня всего 17 операций ( ITransform s). На сортировку сейчас уходит 15 секунд lol / fail.

Добавлено 23 августа: Посмотрите в следующем разделе кода, как я улучшил сортировку до чего-то, что действительно работает, еще раз.

Редактировать 8/25: Ситуация снова стала неприятной, когда я скрестил 25 элементов, но оказалось, что у меня была небольшая проблема с предварительной сортировкой, которая теперь исправлена.

    private static ITransform[] OrderTransforms(ITransform[] source)
    {
        return OrderTransforms(
            new List<ITransform>(source),
            new Stack<ITransform>(),
            new HashSet<OpCode>(source.SelectMany(transform => transform.RemovedOpCodes)),
            source.Aggregate(InstructionSemantics.None, (preventedSemantics, transform) => preventedSemantics | transform.RemovedSemantics)
            );
    }

    private static ITransform[] OrderTransforms(List<ITransform> source, Stack<ITransform> selected, HashSet<OpCode> preventAdd, InstructionSemantics preventSemantics)
    {
        if (source.Count == 0 && preventAdd.Count == 0)
            return selected.ToArray();

        for (int i = source.Count - 1; i >= 0; i--)
        {
            var transform = source[i];
            if ((preventSemantics & transform.InsertedSemantics) != 0)
                continue;

            if (preventAdd.Intersect(transform.InsertedOpCodes).Any())
                continue;

            selected.Push(transform);
            source.RemoveAt(i);
#if true
            var result = OrderTransforms(source, selected, new HashSet<OpCode>(preventAdd.Except(transform.RemovedOpCodes).Union(transform.PreventOpCodes)), (preventSemantics & ~transform.RemovedSemantics) | transform.PreventSemantics);
#else // this is even slower:
            OpCode[] toggle = preventAdd.Intersect(transform.RemovedOpCodes).Union(transform.PreventOpCodes.Except(preventAdd)).ToArray();
            preventAdd.SymmetricExceptWith(toggle);
            var result = OrderTransforms(source, selected, preventAdd, (preventSemantics & ~transform.RemovedSemantics) | transform.PreventSemantics);
            preventAdd.SymmetricExceptWith(toggle);
#endif
            if (result != null)
                return result;

            source.Insert(i, transform);
            selected.Pop();
        }

        return null;
    }

В попытке вернуть свою награду, Я сократил время сортировки с 15380 с до 173 мс, эвристически предварительно подготовив массив, за которым сразу следует маршрутизация сортировки, описанная выше.

private static ITransform[] PreSortTransforms(ITransform[] source)
{
    // maps an opcode to the set of transforms that remove it
    ILookup<OpCode, ITransform> removals =
        source
        .SelectMany(transform => transform.RemovedOpCodes.Select(opcode => new
        {
            OpCode = opcode,
            Transform = transform
        }))
        .ToLookup(item => item.OpCode, item => item.Transform);

    // maps an opcode to the set of transforms that add it
    ILookup<OpCode, ITransform> additions =
        source
        .SelectMany(transform => transform.InsertedOpCodes.Select(opcode => new
        {
            OpCode = opcode,
            Transform = transform
        }))
        .ToLookup(item => item.OpCode, item => item.Transform);

    // maps a set of items (A) to a set of items (B), where ALL elements of B must come before SOME element of A
    ILookup<IEnumerable<ITransform>, ITransform> weakForwardDependencies =
        removals
        .SelectMany(item => additions[item.Key].Select(dependency => new
        {
            Transform = item,
            Dependency = dependency
        }))
        .ToLookup(item => item.Transform.AsEnumerable(), item => item.Dependency);

    /* For items in the previous map where set A only had one element, "somewhat" order the
     * elements of set B before it. The order doesn't [necessarily] hold when a key from one
     * relationship is a member of the values of another relationship.
     */
    var ordered =
        weakForwardDependencies
        .Where(dependencyMap => dependencyMap.Key.SingleOrDefault() != null)
        .SelectMany(dependencyMap => dependencyMap.AsEnumerable());

    // Add the remaining transforms from the original array before the semi-sorted ones.
    ITransform[] semiSorted = source.Except(ordered).Union(ordered).ToArray();

    return semiSorted;
}
2
ответ дан 17 December 2019 в 02:31
поделиться

Поскольку то, может ли элемент X появиться следующим в списке, зависит не только от последнего элемента в списке, но и от предыдущих элементов, вы правы, говоря, что топологическая сортировка слишком сильный. Это более общая проблема поиска, поэтому я бы попробовал более общее решение: либо поиск с возвратом, либо динамическое программирование. Первое всегда можно сделать, но иногда это происходит невероятно медленно;

0
ответ дан 17 December 2019 в 02:31
поделиться

Я думаю, вы здесь говорите об алгоритме упорядочения, а не об алгоритме сортировки. То есть вы хотите найти упорядочение, имеющее перечисленные свойства.

Я был бы удивлен, если бы уже существовал конкретный алгоритм упорядочивания, который удовлетворял бы этим свойствам.

Имейте в виду, что вы не сможете найти упорядочение для заданного набора операций. На самом деле может даже не быть частичного упорядочивания / решетки. Тривиальный пример:

op1(adds(1),removes(2))
op2(adds(2),removes(1))
1
ответ дан 17 December 2019 в 02:31
поделиться

Звуки например топологическая сортировка , представьте каждую операцию как узел в ориентированном графе с ребрами, являющимися упомянутыми вами ограничениями.


Изменить: @ 280Z28 прокомментировал этот ответ:

Сейчас я использую топологическую сортировку, но технически она слишком сильна. Мне нужен какой-то способ иметь "слабые" группы ребер (одно или несколько ребер группы сохраняются в окончательном порядке)

I ' Я не уверен, что следую тому, что вы, ребята, относительно слабых групп ребер, если это относится к разрывным циклам, то топологическая сортировка может это сделать, как я сделал это, чтобы поддерживать в счетчике который показал, сколько непосещенных узлов указывают на этот узел. Затем для каждой итерации вы работаете с (одним из) узлов с минимальным в счетчике , если в счетчике не равен нулю, это означает, что существует цикл, и вы произвольно прерываете цикл в чтобы завершить сортировку.

3
ответ дан 17 December 2019 в 02:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: