Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

11.3. Изучение сортировки алгоритмической линзы 529

Легко видеть, что пробеги вида ведра в O (n + N) время и используют O (n + N)

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

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

Стабильная сортировка

Сортируя пары значения ключа, важная проблема - то, как обработаны равные ключи. Позвольте S = ((k0, x0)..., (kn-1, xn-1)) быть последовательностью таких записей. Мы говорим, что алгоритм сортировки стабилен, если, для каких-либо двух записей (ki, xi) и (k j, x j) S, такого, что ki = k j и (ki, xi) предшествует (k j, x j) в S прежде, чем сортировать (то есть, я <j), вход (ki, xi) также предшествует входу (k j, x j) после сортировки. Стабильность важна для алгоритма сортировки, потому что заявления могут хотеть сохранить начальный заказ элементов с тем же самым ключом.

Наше неофициальное описание вида ведра в Кодовом Фрагменте 11.8 не делает гарантированный - antee стабильность. Это не врожденное от самого метода вида ведра, однако, поскольку мы можем легко изменить наше описание, чтобы сделать вид ведра стабильным, все еще сохраняя его O (n + N) продолжительность. Действительно, мы можем получить стабильный алгоритм вида ведра, всегда удаляя первый элемент из последовательности S и из последовательностей B [я] во время выполнения алгоритма.

Вид корня

Одна из причин, что стабильная сортировка так важна, - то, что она позволяет подходу вида ведра быть примененным к более общим контекстам, чем к целым числам вида. Предположим, например, что мы хотим сортировать записи с ключами, которые являются парами (k, l), где k и

l - целые числа в диапазоне [0, N- 1], для некоторого целого числа N³ 2. В контексте такой

как это, естественно определить заказ на этих ключах, используя лексикографическое

(словарь) соглашение, где (k1, l1) <(k2, l2), если k1 <k2 или если k1 = k2 и l1 <l2 (Раздел 8.1.2). Это - попарная версия лексикографической функции сравнения, обычно относился к строкам символов равной длины (и она легко делает вывод к кортежам d чисел для d> 2).

Алгоритм вида корня сортирует последовательность S записей с ключами, которые являются парами, применяя стабильный вид ведра на последовательность дважды; сначала используя один компонент пары как ключ заказа и затем использование второго компонента. Но какой заказ правилен? Должны мы сначала вид на k's (первый компонент) и затем на l's (второй компонент), или это должно быть наоборот?

530

Глава 11. Сортировка, наборы и выбор

Прежде чем мы ответим на этот вопрос, мы рассматриваем следующий пример. Пример 11.5: Рассмотрите следующую последовательность S (мы показываем только ключи):

S = ((3, 3), (1, 5), (2, 5), (1, 2), (2, 3), (1, 7), (3, 2), (2, 2)).

Если мы сортируем S устойчиво на первом компоненте, то мы получаем последовательность

S1 = ((1, 5), (1, 2), (1, 7), (2, 5), (2, 3), (2, 2), (3, 3), (3, 2)).

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

S1,2 = ((1, 2), (2, 2), (3, 2), (2, 3), (3, 3), (1, 5), (2, 5), (1, 7)),

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

S2 = ((1, 2), (3, 2), (2, 2), (3, 3), (2, 3), (1, 5), (2, 5), (1, 7)).

Если мы тогда устойчиво сортируем последовательность S2, используя первый компонент, то мы получаем se-айву

S2,1 = ((1, 2), (1, 5), (1, 7), (2, 2), (2, 3), (2, 5), (3, 2), (3, 3)),

который является действительно последовательностью S лексикографически заказанный.

Так, от этого примера нас убеждают полагать, что мы должны сначала сортировать использование второго компонента и с другой стороны использование первого компонента. Эта интуиция точно правильная. Первым устойчиво сортировка вторым компонентом и с другой стороны первым компонентом, мы гарантируем, что, если два записей равны во втором виде (первым компонентом), то их относительный заказ в стартовой последовательности (который сортирован вторым компонентом) сохранен. Таким образом получающаяся последовательность, как гарантируют, будет сортирована лексикографически каждый раз. Мы оставляем определение того, как этот подход может быть расширен на, утраивается и другие d-кортежи чисел как простое осуществление (Упражнение R-11.20). Мы можем суммировать эту секцию следующим образом: Суждение 11.6: Позвольте S быть последовательностью n пар значения ключа, у каждой из которых есть a

ключ (k1, k2..., kd), где ki - целое число в диапазоне [0, N- 1] для некоторого целого числа

N³ 2. Мы можем сортировать S лексикографически вовремя O (d (n + N)) использование вида корня.

Столь же важный, как это, сортировка не единственная интересная проблема, имеющая дело с

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