
- •Технология программирования
- •7. Простейшие алгоритмы сортировки (пузырьковая, вставкой, выбором).
- •8. Эффективные алгоритмы сортировки (быстрая, шелловская, пирамидальная, поразрядная). Сортировка подсчетом.
- •3. Неустойчивая.
- •5. Поведение неестественное.
- •Сортировка происходит на месте.
- •Неустойчивая.
- •Поведение неестественное.
- •Неустойчивая.
- •Поведение неестественное.
8. Эффективные алгоритмы сортировки (быстрая, шелловская, пирамидальная, поразрядная). Сортировка подсчетом.
Быстрая сортировка
1. Общее быстродействие O(n*log(n)). Наиболее быстрая сортировка для неупорядоченных массивов с 50 и более элементами.
2. Требует дополнительной памяти.
3. Неустойчивая.
5. Поведение неестественное.
Метод основан на подходе "Разделяй и властвуй".
Быструю сортировку нетрудно реализовать, она хорошо работает на различных видах входных данных и во многих случаях требует меньше затрат ресурсов по сравнению с другими методами сортировки. На выполнение сортировки N элементов в среднем затрачивается время, пропорциональное N log N и для него характерны исключительно короткие внутренние циклы.
Его недостатком является то, что он неустойчив, для его выполнения в наихудшем случае требуется N2 операций.
Наиболее быстрой является сортировка для неупорядоченных массивов с 50 и более элементами.
Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма таковы:
Выбираем в массиве некоторый элемент, который будем называть опорным элементом. С точки зрения корректности алгоритма выбор опорного элемента безразличен. С точки зрения повышения эффективности алгоритма выбираться должна медиана, но без дополнительных сведений о сортируемых данных её обычно невозможно получить. Известные стратегии: выбирать постоянно один и тот же элемент, например, средний или последний по положению; выбирать элемент со случайно выбранным индексом.
Операция разделения массива: реорганизуем массив таким образом, чтобы все элементы со значением меньшим или равным опорному элементу, оказались слева от него, а все элементы, превышающие по значению опорный — справа от него. Обычный алгоритм операции:
Два индекса — i и j, приравниваются к минимальному и максимальному индексу разделяемого массива, соответственно.
Вычисляется индекс опорного элемента m.
Индекс i последовательно увеличивается до тех пор, пока i-й элемент не окажется больше либо равен опорному.
Индекс j последовательно уменьшается до тех пор, пока j-й элемент не окажется меньше либо равен опорному.
Если i = j — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.
Если i < j — найденную пару элементов нужно обменять местами и продолжить операцию разделения с тех значений i и j, которые были достигнуты. Следует учесть, что если какая-либо граница (i или j) дошла до опорного элемента, то при обмене значение m изменяется на i-й или j-й элемент соответственно, изменяется именно индекс опорного элемента и алгоритм продолжает свое выполнение.
Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента.
Базой рекурсии являются наборы, состоящие из одного или двух элементов. Первый возвращается в исходном виде, во втором, при необходимости, сортировка сводится к перестановке двух элементов. Все такие отрезки уже упорядочены в процессе разделения.
Рассмотрим пример.
9i 6 1 3 2j
Находим медиану (m =1).
Индексы i и j присваиваем первому и последнему элементам соответственно.
Сравниваем: 9>=1? да. 2<=1? нет => j сдвигается влево, i остается на месте.
9i 6 1 3j 2
Сравниваем: 9>=1? да. 3<=1? нет => j сдвигается влево, i остается на месте
9i 6 1j 3 2
Сравниваем: 9>=1? да. 1<=1? да => меняем местами i-ый и j-ый элементы.
1i 6 9j 3 2
Сравниваем: 1>=1? да. 9<=1? нет => j сдвигается влево, i остается на месте
1i 6j 9 3 2
Сравниваем: 1>=1? да. 6<=1? нет => j сдвигается влево, i остается на месте
1ij 6 9 3 2
i = j — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.
Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента:
1 | 6i 9 3 2j
Сравниваем: 6>=9? нет. 2<=9? да => i сдвигается вправо, j остается на месте.
1 | 6 9i 3 2j
Сравниваем: 9>=9? да. 2<=9? да => меняем местами i-ый и j-ый элементы.
1 | 6 2i 3 9j
Сравниваем: 2>=9? нет. 9<=9? да => i сдвигается вправо, j остается на месте
1 | 6 2 3i 9j
Сравниваем: 3>=9? нет. 9<=9? да => i сдвигается вправо, j остается на месте
1 | 6 2 3 9ij
i = j — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.
Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента:
1 | 6i 2 3j | 9
Сравниваем: 6>=2? да. 3<=2? нет => j сдвигается влево, i остается на месте
1 | 6i 2j 3 | 9
Сравниваем: 6>=2? да. 2<=2? да => меняем местами i-ый и j-ый элементы
1 | 2i 6j 3 | 9
Сравниваем: 2>=2? да. 6<=2? нет => => j сдвигается влево, i остается на месте
1 | 2ij 6 3 | 9
i = j — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.
Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента:
1 2 | 6i 3j | 9
Аналогично сравниваем 6 и 3. Получаем: 1 2 3 6 9
Сортировка методом Шелла