2008-09-22 1 views
12

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

  1. Stable (не изменяет относительный порядок элементов с равные ключи.)
  2. на месте или почти на месте (O (не войти п) стек хорошо, но не O (N) использование пространства или кучи распределение.
  3. О (п войти п) временную сложность.

Также обратите внимание, что структура данных, подлежащая сортировке, является arra у.

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

+0

Будут ли ваши данные иметь регулярные обновления? Если это так, то положить в один огромный массив - плохая идея. Рассмотрим структуру, которая может быть фрагментирована, например, B-дерево или веревка. – finnw 2008-10-04 14:35:19

+0

Кажется странным быть довольным сложностью времени O (n log n), но иметь проблему с использованием пространства O (n). Не могли бы вы рассказать о своей фактической цели? есть риск, что вы попадаете в ловушку проблем XY. – mikera 2012-01-27 15:51:23

ответ

3

Как насчет быстрой сортировки?

Обмен может сделать это тоже, может быть более «стабильным» на ваших условиях, но quicksort быстрее.

+1

Пример, приведенный в http://en.wikipedia.org/wiki/Quicksort#Algorithm, является стабильным, хотя и не самой эффективной версией qsort. – freespace 2008-09-22 03:29:43

+0

Я понимаю, что вариации Quicksort могут быть стабильными или эффективными, но не одновременно. – cjm 2008-09-22 03:49:39

10

Слияние может быть написано на месте, я верю. Это лучший маршрут.

+0

http://comjnl.oxfordjournals.org/cgi/content/abstract/35/6/643 Это, вероятно, алгоритм, который вы хотите. – 2009-08-17 20:29:01

1

Возможно, shell sort? Если я правильно изучил курс данных, он, как правило, был стабильным, но хуже время O (n log^2 n), хотя оно выполняет O (n) на почти отсортированных данных. Он основан на сортировке вставки, поэтому он сортируется на месте.

+5

Так что это иногда стабильно? Я думаю, что это точное определение нестабильности :) – leppie 2009-02-25 11:17:58

+0

Иногда бывает иначе, чем обычно :) – Ryan 2009-02-25 18:06:08

3

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

Ваш лучший выбор - это, вероятно, изменение стабильной нестабильной сортировки, что сделает ее менее эффективной.

8

Примечание: стандартная быстрая сортировка не O (n log n)! В худшем случае это может занять до O (n^2) времени. Проблема в том, что вы можете опираться на элемент, который далек от медианного, так что ваши рекурсивные вызовы очень неуравновешенны.

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

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

Кстати, сортировка слияния может быть выполнена на месте, хотя сложно сделать как на месте, так и стабильно.

+1

Основы алгоритмов pg 237 описывает способ сделать quicksort O (n log n) * except *, если все элементы одинаковы. Он рекурсивно выбирает медианную точку для поворота, возвращая скошенный список, который затем сортирует, а затем рекурсирует вниз. Сказав это, я согласен, что медиана 5 - лучший способ сделать это. – 2008-09-24 18:22:39

2

Существует класс стабильных алгоритмов слияния на месте, хотя они сложны и линейны с довольно высокой константой, скрытой в O (n). Чтобы узнать больше, посмотрите на this article, and its bibliography.

Редактировать: фаза слияния является линейной, поэтому mergesort является nlog_n.

1

Не беспокойтесь о O (n log n), пока не сможете продемонстрировать, что это имеет значение. Если вы можете найти алгоритм O (n^2) с существенно более низкой константой, пойдите для него!

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

Вкратце: выполните несколько тестов.

2

Поскольку ваши элементы находятся в массиве (а не, скажем, в связанном списке), у вас есть информация об их первоначальном заказе, доступная вам в самих индексах массива. Вы можете воспользоваться этим путем написания сортировки и сравнения функций, чтобы быть в курсе индексов:

function cmp(ar, idx1, idx2) 
{ 
    // first compare elements as usual 
    rc = (ar[idx1]<ar[idx2]) ? -1 : ((ar[idx1]>ar[idx2]) ? 1 : 0); 

    // if the elements are identical, then compare their positions 
    if(rc != 0) 
     rc = (idx1<idx2) ? -1 : ((idx1>idx2) ? 1 : 0); 

    return rc; 
} 

Этот метод может быть использован для любого вида стабильной, до тех пор, как своего рода выполняет только элемент свопы. Индексы элементов будут меняться, но относительный порядок идентичных элементов останется неизменным, поэтому сортировка остается надежной. Он не будет работать из коробки для такого рода, как heapsort, потому что исходная кучка «отбрасывает» относительный порядок, хотя вы могли бы приспособить идею к другим видам.

2

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

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

Я использовал этот метод с функцией Cqsort(), чтобы избежать написания собственных. Каждая запись содержит 32-разрядное целое число и заполняется начальным порядковым номером перед вызовом qsort().

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

Ваш пробег может отличаться, поэтому всегда помните: Измерьте, не угадайте!

0

Возможно, я немного в колесе, но мне нравится сортировка с использованием ручного кодирования. Это просто, стабильно и хорошо. Дополнительное временное хранилище, которое ему нужно, это всего лишь N*sizeof(int), что не так уж плохо.

1

Существует красивый список функций сортировки on wikipedia, который поможет вам найти любую функцию сортировки, которую вы используете.

Например, чтобы задать конкретный вопрос, похоже, что сортировка на месте на месте - это то, что вы хотите.

Однако вы также можете взглянуть на strand sort, у него есть интересные свойства.

2

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

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

Итак, в заключение, перечислить все ваши вопросы и запустить быструю сортировку в списке

1

я реализовал stable in-place quicksort и stable in-place merge sort. Сорт слияния немного быстрее и гарантированно работает в O (n * log (n)^2), но не в быстрой сортировке. Оба используют O (log (n)) пространство.

 Смежные вопросы

  • Нет связанных вопросов^_^