Каков подходящий алгоритм сортировки для встроенной системы? - PullRequest
9 голосов
/ 09 сентября 2011

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

  1. Поскольку это очень ограниченная память, сложность пространства является основным фактором.
  2. Поскольку количество элементов для сортировки, как правило, будет небольшим,и сортировка будет происходить только изредка, временная сложность не обязательно является основным фактором.
  3. Для моего приложения требуется стабильный алгоритм.
  4. Поскольку это встроенная система, размер кодафактор.
  5. Нет никакой гарантии, что данные изначально будут в почти отсортированном порядке.

Я рассмотрел следующие алгоритмы:

  • пузырьковая сортировка (да, хотя мне стыдно это говорить)
  • сортировка гномов
  • сортировка вставками
  • сортировка слиянием на месте (хотя мне кажется, чтоэто лучше для связных списков, чем для массивов?)

Хотя ответ (для моих точных обстоятельств) вполне может быть: "Э-э, это не имеет значения, используйте сортировку по пузырям длявсе мы заботимся ", этот ответне очень полезно В общем, какие алгоритмы сортировки используются во встроенных системах?

Ответы [ 6 ]

9 голосов
/ 09 сентября 2011

Сортировка вставок тоже подойдет, на практике она работает быстро, стабильна и на месте.Это очень сильно связано с сортировкой gnome, быстрее на практике, но для сортировки gnome код немного меньше и занимает меньше вспомогательного пространства (не с точки зрения большого O, разница в константе)

edit:да, я немного испортил и перевернул их - я, вероятно, не должен отвечать на вопросы до того, как выпью кофе ... раньше говорилось, что сортировка вставок имеет меньше кода и места, чем сортировка gnome

6 голосов
/ 09 сентября 2011

Не стыдитесь пузырьковых сортов, у них есть свое место.Если ваш набор данных имеет небольшой размер, его легко кодировать и он стабилен, если вы все делаете правильно (никогда не меняйте местами одинаковые элементы).

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

Это , особенно , если, как вы упомянули в комментарии к другомуответ, размер вашего набора данных составляет около 11. Если не считать алгоритма сортировки, явно разработанного , чтобы быть преднамеренно ужасным, любой алгоритм легко справится с таким размером достаточно быстро.

Если ваша среда не 'Чтобы предложить стабильную сортировку, я бы просто пошел с пузырьковой сортировкой, учитывая ваши ограничения и свойства.


Фактически, используя следующую программу вместе с утилитой time, я обнаружил, чтоПроцессорное время, используемое для qsort и сортировки пузырьков, начинает меняться только после того, как количество элементов достигло 10 000.

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

#include <stdio.h>
#include <stdlib.h>

static int data[10000];
#define SZDATA (sizeof (*data))
#define NMDATA (sizeof (data) / sizeof (*data))

int compfn (const void *a, const void *b) {
    if (*((int*)a) > *((int*)b))
        return 1;
    if (*((int*)a) < *((int*)b))
        return -1;
    return 0;
}

int main (void) {
    int i, tmp, swapped, count;

    for (i = 0; i < NMDATA; i++)
        data[i] = (i * 3) % 11;

    if (0) {
        qsort (data, NMDATA, SZDATA, compfn);
    } else {
        swapped = 1;
        count = NMDATA;
        while (swapped) {
            swapped = 0;
            for (i = 1; i < count; i++) {
                if (data[i] < data[i-1]) {
                    tmp = data[i];
                    data[i] = data[i-1];
                    data[i-1] = tmp;
                    swapped = 1;
                }
            }
            count --;
        }
    }

    //for (i = 0; i < NMDATA; i++)
        //printf ("%10d\n", data[i]);

    return 0;
}

Изменяя размер массива data и оператора if (0), я получил следующие результаты (в миллисекундах) по пять прогонов для каждого случая:

Data size | qsort | bubble
----------+-------+-------
      100 |    61 |     76
          |    76 |     76
          |    77 |     61
          |    61 |     60
          |    61 |     61  avg qsort = 67, bubble = 67

     1000 |    77 |     93
          |    61 |     45
          |    76 |     77
          |    77 |     76
          |    76 |     77  avg qsort = 73, bubble = 74
          |       |
    10000 |    92 |    414
          |    77 |    413
          |    61 |    413
          |    76 |    405
          |    61 |    421  avg qsort = 73, bubble = 413

Я подозреваю, что более быстрые пузырьковые сортировки с небольшим набором данных таковы из-за отсутствия вызовов функций.

Что нужно предпринятьот этого заключается в том, что для небольших наборов данных эффективность алгоритма часто не важна, поскольку такие вещи, как big-O, обычно актуальны по мере того, как наборы данных становятся больше.

Однако этот тест был выполнен в моя среда и ваша среда могут значительно отличаться.Я бы предложил выполнить те же измерения в вашей среде - реализовать сортировку по пузырькам и рассмотреть возможность перехода к более сложному алгоритму только в том случае, когда это станет необходимым.


По предложению комментатора я повторяюзапустил тесты, используя srand(42), а затем rand() для заполнения элементов массива.В этом случае результаты были только немного хуже для пузырьковой сортировки: 642 против 413 миллисекунд для 10000 элементов и 82 против 74 миллисекунд для 1000.

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

Тем не менее, помните мой предыдущий совет: вам нужно рассчитать время в вашем собственном среда.Результаты могут быть совершенно разными.Вы можете использовать код, который я предоставил в качестве основы для этого.Серьезно, если какой-либо метод, который вы выберете, займет меньше секунды, он, вероятно, более чем подходит для ваших целей.

3 голосов
/ 09 сентября 2011

Тот факт, что система встроена или нет, не имеет значения.Важны именно те факторы, которые вы перечисляете: ограничения размера кода, доступная оперативная память, необходимая скорость и количество элементов.

С учетом того, что вы обрисовали в общих чертах, пузырьковая сортировка является вполне приемлемым решением: она небольшая, предсказуемая, легко на память, и очень легко реализовать и отладить.В начале 1980-х годов я увидел доказательство, заключающее, что сортировка пузырьков является оптимальным по времени для n ≤ 11. Возможно, современные быстрые сортировки слегка изменят это, но я сомневаюсь, что безубыточность может быть значительно уменьшена.

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

2 голосов
/ 09 сентября 2011

уберите «на встроенных системах» и измените вопрос на «В общем, какие алгоритмы сортировки полезны».Далее просто попробуйте их!Что вы пробовали до сих пор, каково было потребление памяти, какое время выполнения и каков был размер кода?

Встроенный или настольный компьютер, вы должны выполнять эти эксперименты и задавать эти вопросы.Нет общего ответа, потому что нет общих требований.Каждое решение имеет свое место в зависимости от требований.Один размер подходит всем и никому не подходит.На самом деле вопрос в том, каковы ваши требования, тогда вы беспокоитесь о внедрении и выполнении этих требований.Требуется ли что-то вроде этого, могло ли это быть решено иначе?Где этот вид вписывается в ваш общий показатель производительности?Какие еще длинные палки в палатке?

Так же, как на рабочем столе, закодируйте их, попробуйте и посмотрите, что вы придумали.Нет причин смущаться упоминанием пузырькового типа.Если в ваших требованиях отсутствуют показатели производительности или размера, пузырьковые сортировки хороши, каждый может прочитать и понять код, простой, поддерживаемый, не полагающийся на библиотеки или версии библиотек и т. Д. Нельзя сказать ничего плохого (если естьнет требований к производительности).

1 голос
/ 29 августа 2013

Сортировка во встроенных системах , статья Найджела Джоунса о Embedded Gurus заслуживает внимания.

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

0 голосов
/ 10 сентября 2011

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

  • Детерминированное время выполнения
  • Детерминированное использование памяти
  • Минимизация времени выполнения
  • Минимизация использования памяти
  • Размер кода

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

Вы можете, как кажется, в этом случае расставить приоритеты в вопросах использования памяти над скоростью выполнения.

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

Все это говорит, что в целях ускорения разработки всегда стоит попробовать стандартныйФункция qsort () поставляется со стандартной библиотекой вашего компилятора.Если это работает для вас и отвечает вашим ограничениям, дальнейшая работа не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...