Сортировка Шелла — различия между версиями
м (rollbackEdits.php mass rollback) |
|||
(не показано 8 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
− | '''''Сортировка Шелла''''' (англ. Shellsort) | + | '''''Сортировка Шелла''''' (англ. Shellsort) — алгоритм сортировки, являющийся усовершенствованным вариантом [[Сортировка вставками|сортировки вставками]]. |
==Алгоритм== | ==Алгоритм== | ||
Каждый проход в алгоритме характеризуется смещением <tex>h_i</tex>, таким, что сортируются элементы отстающие друг от друга на <tex>h_i</tex> позиций. | Каждый проход в алгоритме характеризуется смещением <tex>h_i</tex>, таким, что сортируются элементы отстающие друг от друга на <tex>h_i</tex> позиций. | ||
− | Шелл предлагал использовать <tex>h_t = N/2</tex>, <tex>h_{t-1} = h_t/2</tex> | + | Шелл предлагал использовать <tex>h_t = N/2</tex>, <tex>h_{t-1} = h_t/2</tex>, <tex>\ldots</tex> , <tex>h_0 = 1</tex>. Возможны и другие смещения, но <tex>h_0 = 1</tex> всегда. |
* Начало. | * Начало. | ||
Строка 9: | Строка 9: | ||
* '''Шаг 1.''' Разобьем массив на списки элементов, отстающих друг от друга на <tex>h_i</tex>. Таких списков будет <tex>h_i</tex>. | * '''Шаг 1.''' Разобьем массив на списки элементов, отстающих друг от друга на <tex>h_i</tex>. Таких списков будет <tex>h_i</tex>. | ||
* '''Шаг 2.''' Отсортируем элементы каждого списка [[Сортировка вставками|сортировкой вставками]]. | * '''Шаг 2.''' Отсортируем элементы каждого списка [[Сортировка вставками|сортировкой вставками]]. | ||
− | * '''Шаг 3.''' Объединим списки обратно в массив. Уменьшим <tex>i</tex> | + | * '''Шаг 3.''' Объединим списки обратно в массив. Уменьшим <tex>i</tex>. Если <tex>i</tex> неотрицательно — вернемся к шагу 1 |
* Конец. | * Конец. | ||
Строка 35: | Строка 35: | ||
|style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''42, 56'' <tex>\} </tex> <tex>\{</tex> ''43, 93'' <tex>\} </tex> <tex>\{</tex> ''12, 16'' <tex>\} </tex> <tex>\{</tex> ''55, 78'' <tex>\} </tex> | |style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''42, 56'' <tex>\} </tex> <tex>\{</tex> ''43, 93'' <tex>\} </tex> <tex>\{</tex> ''12, 16'' <tex>\} </tex> <tex>\{</tex> ''55, 78'' <tex>\} </tex> | ||
|style="background-color:#FFF;padding:2px 10px"| ''42, 43, 12, 55, 56, 93, 16, 78'' | |style="background-color:#FFF;padding:2px 10px"| ''42, 43, 12, 55, 56, 93, 16, 78'' | ||
− | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1 | + | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1. <tex>i \geqslant 0</tex>, перейдем к шагу 1. |
|- | |- | ||
| ''Шаг 1'' <tex>i = 1</tex> | | ''Шаг 1'' <tex>i = 1</tex> | ||
Строка 53: | Строка 53: | ||
|style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''12, 16, 42, 56'' <tex>\} </tex> <tex>\{</tex> ''43, 55, 78, 93'' <tex>\} </tex> | |style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''12, 16, 42, 56'' <tex>\} </tex> <tex>\{</tex> ''43, 55, 78, 93'' <tex>\} </tex> | ||
|style="background-color:#FFF;padding:2px 10px"| ''12, 43, 16, 55, 42, 78, 56, 93'' | |style="background-color:#FFF;padding:2px 10px"| ''12, 43, 16, 55, 42, 78, 56, 93'' | ||
− | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1 | + | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1. <tex>i \geqslant 0</tex>, перейдем к шагу 1. |
|- | |- | ||
| ''Шаг 1'' <tex>i = 0</tex> | | ''Шаг 1'' <tex>i = 0</tex> | ||
Строка 71: | Строка 71: | ||
|style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''12, 16, 42, 43, 55, 56, 78, 93'' <tex>\} </tex> | |style="background-color:#FFF;padding:2px 10px"| <tex>\{</tex> ''12, 16, 42, 43, 55, 56, 78, 93'' <tex>\} </tex> | ||
|style="background-color:#FFF;padding:2px 10px"| ''12, 16, 42, 43, 55, 56, 78, 93'' | |style="background-color:#FFF;padding:2px 10px"| ''12, 16, 42, 43, 55, 56, 78, 93'' | ||
− | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1 | + | |style="background-color:#FFF;padding:2px 10px"| Объединили списки в массив. Уменьшаем <tex>i</tex> на 1. <tex>i<0</tex>. |
|} | |} | ||
==Анализ метода Шелла== | ==Анализ метода Шелла== | ||
Понятно, что сложность алгоритма зависит от оптимальности выбора набора <tex>h_i</tex>. | Понятно, что сложность алгоритма зависит от оптимальности выбора набора <tex>h_i</tex>. | ||
− | Массив где для любого <tex>i</tex> верно <tex> a_i \leqslant a_{i+h}</tex>, назовем <tex>h</tex> упорядоченным. | + | Массив, где для любого <tex>i</tex> верно <tex> a_i \leqslant a_{i+h}</tex>, назовем <tex>h</tex> упорядоченным. |
Строка 82: | Строка 82: | ||
|author= Д.Х. Ханту | |author= Д.Х. Ханту | ||
|statement= | |statement= | ||
− | Среднее число инверсий в <tex>h</tex> упорядоченной перестановке множества <tex>\{</tex> ''1, 2, | + | Среднее число инверсий в <tex>h</tex> упорядоченной перестановке множества <tex>\{</tex> ''1, 2, <tex>\ldots</tex> , <tex>n \}</tex> равно |
<tex> f(n,h) = \dfrac{2^{2q-1}q!q!}{(2q+1)!}(\binom{h}{2}q(q+1) + \binom{r}{2}(q+1)-1/2\binom{h-r}{2}q) </tex>, где <tex>q = \frac{n}{h} </tex> и <tex> r = n\,\bmod\,h </tex> | <tex> f(n,h) = \dfrac{2^{2q-1}q!q!}{(2q+1)!}(\binom{h}{2}q(q+1) + \binom{r}{2}(q+1)-1/2\binom{h-r}{2}q) </tex>, где <tex>q = \frac{n}{h} </tex> и <tex> r = n\,\bmod\,h </tex> | ||
Строка 93: | Строка 93: | ||
|about= | |about= | ||
|statement= | |statement= | ||
− | Если последовательность смещений <tex>h_{t-1}, | + | Если последовательность смещений <tex>h_{t-1}, \ldots , h_1, h_0</tex>, удовлетворяют условию <tex> h_{s+1}\,\bmod\,h_s = 0</tex> при <tex>t-1>s\geqslant0</tex>, то среднее число операций равно |
<tex>D = \sum_{t-1>s\geqslant0}^{} (r_sf(q_s+1,h_{s+1}/h_s) + (h_s - r_s)f(q_s,h_{s+1}/h_s))</tex>, где <tex>r_s=N\,\bmod\,h_s</tex>, <tex>q_s = \frac{N}{h_s}</tex>, <tex> h_t = Nh_{t-1}</tex>, а функция <tex>f</tex> определяется формулой из теоремы. | <tex>D = \sum_{t-1>s\geqslant0}^{} (r_sf(q_s+1,h_{s+1}/h_s) + (h_s - r_s)f(q_s,h_{s+1}/h_s))</tex>, где <tex>r_s=N\,\bmod\,h_s</tex>, <tex>q_s = \frac{N}{h_s}</tex>, <tex> h_t = Nh_{t-1}</tex>, а функция <tex>f</tex> определяется формулой из теоремы. | ||
Строка 99: | Строка 99: | ||
− | Доказательство данных теоремы и леммы изложено в | + | Доказательство данных теоремы и леммы изложено в книге, предложенной к прочтению. |
− | В первом приближении функция <tex>f(n,h)</tex> равна <tex> (\sqrt{\pi}/8)n^{3/2}h^{1/2}</tex>. Следовательно <tex>D</tex> для двух проходов будет примерно пропорционально <tex>2N^2/h+\sqrt{\pi N^3h}</tex>. Поэтому наилучшее значение <tex>h</tex> равно приблизительно <tex>\sqrt[3]{16N/ {\pi}} \approx 1.72\sqrt[3]{N}</tex>, при таком выборе <tex>h</tex> среднее время | + | В первом приближении функция <tex>f(n,h)</tex> равна <tex> (\sqrt{\pi}/8)n^{3/2}h^{1/2}</tex>. Следовательно <tex>D</tex> для двух проходов будет примерно пропорционально <tex>2N^2/h+\sqrt{\pi N^3h}</tex>. Поэтому наилучшее значение <tex>h</tex> равно приблизительно <tex>\sqrt[3]{16N/ {\pi}} \approx 1.72\sqrt[3]{N}</tex>, при таком выборе <tex>h</tex> среднее время сортировки пропорционально <tex>N^{5/3}</tex>. |
Таким образом, применяя метод Шелла и используя всего 2 прохода, можно сократить время по сравнению с методом простых вставок с <tex>O(N^2)</tex> до <tex>O(N^{1.(6)})</tex>. | Таким образом, применяя метод Шелла и используя всего 2 прохода, можно сократить время по сравнению с методом простых вставок с <tex>O(N^2)</tex> до <tex>O(N^{1.(6)})</tex>. | ||
Строка 112: | Строка 112: | ||
|author= А.А. Папернов, Г.В. Стасевич | |author= А.А. Папернов, Г.В. Стасевич | ||
|statement= | |statement= | ||
− | Если <tex>h_s=2^{s+1}-1</tex> при <tex>0 \leqslant s < t = \left \lfloor ln N \right \rfloor</tex>, то время сортировки есть <tex>O(N^{3/2})</tex>. | + | Если <tex>h_s=2^{s+1}-1</tex> при <tex>0 \leqslant s < t = \left \lfloor \ln N \right \rfloor</tex>, то время сортировки есть <tex>O(N^{3/2})</tex>. |
|proof= | |proof= | ||
− | Достаточно найти оценку числа перезаписей <tex>B_s</tex> на <tex>s</tex> проходе, такую, что бы <tex>B_{t-1}+ | + | Достаточно найти оценку числа перезаписей <tex>B_s</tex> на <tex>s</tex> проходе, такую, что бы <tex>B_{t-1}+\ldots +B_0=O(N^{3/2})</tex>. Для первых <tex>t/2</tex> проходов при <tex> t>s\geqslant t/2</tex> можно воспользоваться оценкой <tex>B_s=O(h_s(N/h_s)^2)</tex>, а для последующих проходов <tex>B_s=O(Nh_{s+2}h_{s+1}/h_s)</tex>, следовательно <tex>B_{t-1}+\ldots +B_0=O(N(2+2^2+\ldots +2^{t/2}+2^{t/2}+\ldots +2^2+2))=O(N^{3/2})</tex>. |
}} | }} | ||
Важно, что эта теорема дает оценку времени выполнения алгоритма в худшем случае. | Важно, что эта теорема дает оценку времени выполнения алгоритма в худшем случае. | ||
− | Дальнейшее улучшение было получено Волганом Праттом. Если все смещения при сортировке выбираются из множества чисел вида <tex>2^p3^q</tex>, меньших <tex>N</tex>, то время выполнения алгоритма будет порядка <tex> | + | Дальнейшее улучшение было получено Волганом Праттом. Если все смещения при сортировке выбираются из множества чисел вида <tex>2^p3^q</tex>, меньших <tex>N</tex>, то время выполнения алгоритма будет порядка <tex>O(N\log^2{N})</tex>. |
− | == | + | == См. также == |
* [[Сортировка выбором]] | * [[Сортировка выбором]] | ||
* [[Сортировка вставками]] | * [[Сортировка вставками]] | ||
* [[Быстрая сортировка]] | * [[Быстрая сортировка]] | ||
− | == | + | == Источники информации == |
− | * Дональд Кнут Искусство программирования, том 3. Сортировка и поиск = The Art of Computer Programming, vol.3. Sorting and Searching. — 2-е изд. — М.: «Вильямс», 2007. — 824 с. — ISBN 5-8459-0082-4 | + | * Дональд Кнут — Искусство программирования, том 3. Сортировка и поиск = The Art of Computer Programming, vol.3. Sorting and Searching. — 2-е изд. — М.: «Вильямс», 2007. — 824 с. — ISBN 5-8459-0082-4 |
− | + | * [http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A8%D0%B5%D0%BB%D0%BB%D0%B0 Сортировка Шелла — Википедия] | |
− | |||
− | [http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A8%D0%B5%D0%BB%D0%BB%D0%B0 Сортировка Шелла | ||
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
− | |||
[[Категория: Сортировка]] | [[Категория: Сортировка]] | ||
+ | [[Категория: Сортировка на сравнениях]] |
Текущая версия на 19:26, 4 сентября 2022
Сортировка Шелла (англ. Shellsort) — алгоритм сортировки, являющийся усовершенствованным вариантом сортировки вставками.
Алгоритм
Каждый проход в алгоритме характеризуется смещением
, таким, что сортируются элементы отстающие друг от друга на позиций. Шелл предлагал использовать , , , . Возможны и другие смещения, но всегда.- Начало.
- Шаг 0. .
- Шаг 1. Разобьем массив на списки элементов, отстающих друг от друга на . Таких списков будет .
- Шаг 2. Отсортируем элементы каждого списка сортировкой вставками.
- Шаг 3. Объединим списки обратно в массив. Уменьшим . Если неотрицательно — вернемся к шагу 1
- Конец.
Пример
Возьмем массив
56, 43, 12, 78, 42, 93, 16, 55 и смещения предложенные Шеллом.До | После | Описание шага |
---|---|---|
Шаг 1 | ||
56, 43, 12, 78, 42, 93, 16, 55 | 56, 42 43, 93 12, 16 78, 55 | Разбили массив на 4 списка. |
Шаг 2 | ||
56, 42 43, 93 12, 16 78, 55 | 42, 56 43, 93 12, 16 55, 78 | Отсортировали элементы списков сортировкой вставками. Количество обменов 2. |
Шаг 3 | ||
42, 56 43, 93 12, 16 55, 78 | 42, 43, 12, 55, 56, 93, 16, 78 | Объединили списки в массив. Уменьшаем | на 1. , перейдем к шагу 1.
Шаг 1 | ||
42, 43, 12, 55, 56, 93, 16, 78 | 42, 12, 56, 16 43, 55, 93, 78 | Разбили массив на 2 списка. |
Шаг 2 | ||
42, 12, 56, 16 43, 55, 93, 78 | 12, 16, 42, 56 43, 55, 78, 93 | Отсортировали элементы списков сортировкой вставками. Количество обменов 4. |
Шаг 3 | ||
12, 16, 42, 56 43, 55, 78, 93 | 12, 43, 16, 55, 42, 78, 56, 93 | Объединили списки в массив. Уменьшаем | на 1. , перейдем к шагу 1.
Шаг 1 | ||
42, 43, 12, 55, 56, 93, 16, 78 | 42, 43, 12, 55, 56, 93, 16, 78 | Разбили массив на 1 список. |
Шаг 2 | ||
42, 43, 12, 55, 56, 93, 16, 78 | 12, 16, 42, 43, 55, 56, 78, 93 | Отсортировали элементы списков сортировкой вставками. Количество обменов 7. |
Шаг 3 | ||
12, 16, 42, 43, 55, 56, 78, 93 | 12, 16, 42, 43, 55, 56, 78, 93 | Объединили списки в массив. Уменьшаем | на 1. .
Анализ метода Шелла
Понятно, что сложность алгоритма зависит от оптимальности выбора набора
. Массив, где для любого верно , назовем упорядоченным.
Теорема (Д.Х. Ханту): |
Среднее число инверсий в упорядоченной перестановке множества 1, 2, , равно
, где и |
Следующая лемма является следствием теоремы выше.
Лемма: |
Если последовательность смещений , удовлетворяют условию при , то среднее число операций равно
, где , , , а функция определяется формулой из теоремы. |
Доказательство данных теоремы и леммы изложено в книге, предложенной к прочтению.
В первом приближении функция
равна . Следовательно для двух проходов будет примерно пропорционально . Поэтому наилучшее значение равно приблизительно , при таком выборе среднее время сортировки пропорционально .Таким образом, применяя метод Шелла и используя всего 2 прохода, можно сократить время по сравнению с методом простых вставок с
до .Используя приведенные выше формулы, порог
преодолеть невозможно, но если убрать ограничение его можно преодолеть.
Теорема (А.А. Папернов, Г.В. Стасевич): |
Если при , то время сортировки есть . |
Доказательство: |
Достаточно найти оценку числа перезаписей | на проходе, такую, что бы . Для первых проходов при можно воспользоваться оценкой , а для последующих проходов , следовательно .
Важно, что эта теорема дает оценку времени выполнения алгоритма в худшем случае.
Дальнейшее улучшение было получено Волганом Праттом. Если все смещения при сортировке выбираются из множества чисел вида
, меньших , то время выполнения алгоритма будет порядка .См. также
Источники информации
- Дональд Кнут — Искусство программирования, том 3. Сортировка и поиск = The Art of Computer Programming, vol.3. Sorting and Searching. — 2-е изд. — М.: «Вильямс», 2007. — 824 с. — ISBN 5-8459-0082-4
- Сортировка Шелла — Википедия