Что общего у сортировки выбором и сортировки вставками
Перейти к содержимому

Что общего у сортировки выбором и сортировки вставками

  • автор:

Что общего у сортировки выбором и сортировки вставками

Содержание:

  • Давайте знакомиться! Я – репетитор по информационным технологиям
  • Чем сложен алгоритм сортировки вставками
  • Видеоролик, посвященный способу сортировки вставками
  • Реализация алгоритма сортировки вставками на языке Паскаль
  • Остались сомнения и недопонимания?

Давайте знакомиться! Я – репетитор по информационным технологиям

Приветствую! Меня зовут Александр Георгиевич, и я явлюсь рейтинговым репетитором по информатике, программированию и математике, работающим на всей территории нашей необъятной родины.

Квинтэссенцией моей профессиональной деятельности является подготовка школьников к успешной сдаче ОГЭ и ЕГЭ по информатике. Студентам я помогаю «закрывать» лабораторный практикум, готовлю к всевозможным зачетам, реализую курсовые и дипломные проекты по программированию и базам данных, а также натаскиваю на сдачу сложных вузовских экзаменов по различным языкам программирования.

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

Историческим стереотипом является тот факт, что информационные технологии – исключительно мужская прерогатива, но в действительности это не так. Лично я веду учеников обоих полов, причем в количественном соотношении ученики-девушки составляют примерно 35-40% от общего числа моих клиентов.

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

Чем сложен алгоритм сортировки вставками

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

Во-первых, у вас должно быть ясное понимание того, как работают циклические конструкции, особенно цикл со счетчиком «for-to-do». Любой алгоритм сортировки данных так или иначе задействует циклические проходы.

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

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

Видеоролик, посвященный способу сортировки вставками

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

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

Реализация алгоритма сортировки вставками на языке Паскаль

Разумеется, я не мог вас оставить без наглядного примера программного кода, реализующего сортировку вставками. В качестве базового языка программирования для реализации данного алгоритма применим язык программирования Паскаль, так как он является наиболее популярным в образовательной сфере.

Условие задачи звучит так:

Дан одномерный массив, состоящий из 10 элементов целого типа. Заполнение элементов массива производится случайным образом из отрезка [-30..30]. Необходимо отсортировать заданный массив сортировкой вставками по возрастанию значения элементов. Вывести элементы массива до и после сортировки.

Остались сомнения и недопонимания?

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

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

Также мы с вами согласуем дополнительные параметры частных уроков, а именно:

  • Интенсивность занятий (количество уроков, проводимых в неделю).
  • Длительность одного занятия.
  • Территориальную принадлежность проводимых частных лекций.

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

Желающих заниматься со мной предостаточно, а количество ученических мест все-таки ограниченно. Не упустите свой шанс заниматься с элитным репетитором по приемлемым ценам и достичь тех вершин, к которым вы так упорно стремитесь!

Сортировка выбором

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

  1. Найти наименьшее значение в списке.
  2. Записать его в начало списка, а первый элемент — на место, где раньше стоял наименьший.
  3. Снова найти наименьший элемент в списке. При этом в поиске не участвует первый элемент.
  4. Второй минимум поместить на второе место списка. Второй элемент при этом перемещается на освободившееся место.
  5. Продолжать выполнять поиcк и обмен, пока не будет достигнут конец списка.

Решение задачи на языке программирования Python:

# Заполняем список из 10 элементов # случайными числами от 1 до 99 и # выводим неотсортированный список на экран. from random import randint N = 10 arr = [] for i in range(N): arr.append(randint(1, 99)) print(arr) # В цикле переменная i хранит индекс ячейки, # в которую записывается минимальный элемент. # Сначала это будет первая ячейка. i = 0 # N - 1, так как последний элемент # обменивать уже не надо. while i  N - 1: # ПОИСК МИНИМУМА # Сначала надо найти минимальное значение # на срезе от i до конца списка. # Переменная m будет хранить индекс ячейки # с минимальным значением. # Сначала предполагаем, что # в ячейке i содержится минимальный элемент. m = i # Поиск начинаем с ячейки следующей за i. j = i + 1 # Пока не дойдем до конца списка, while j  N: # будем сравнивать значение ячейки j, # со значением ячейки m. if arr[j]  arr[m]: # Если в j значение меньше, чем в m, # сохраним в m номер найденного # на данный момент минимума. m = j # Перейдем к следующей ячейке. j += 1 # ОБМЕН ЗНАЧЕНИЙ # В ячейку i записывается найденный минимум, # а значение из ячейки i переносится # на старое место минимума. arr[i], arr[m] = arr[m], arr[i] # ПЕРЕХОД К СЛЕДУЮЩЕЙ НЕОБРАБОТАННОЙ ЯЧЕЙКЕ i += 1 # Вывод отсортированного списка print(arr)
[77, 46, 11, 89, 48, 14, 67, 73, 22, 26] [11, 14, 22, 26, 46, 48, 67, 73, 77, 89]

Сортировка выбором с помощью цикла for и помещения реализации алгоритма в функцию:

from random import randint N = 10 def sel_sort(row): n = len(row) for i in range(n-1): m = i for j in range(i+1, n): if row[j]  row[m]: m = j row[i], row[m] = row[m], row[i] arr = [randint(1, 99) for item in range(N)] print(arr) sel_sort(arr) print(arr)

X Скрыть Наверх

Решение задач на Python

Объяснение алгоритмов сортировки с примерами на Python

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

Обложка поста Объяснение алгоритмов сортировки с примерами на Python

В этой статье будут рассмотрены популярные алгоритмы, принципы их работы и реализация на Python. А ещё сравним, как быстро они сортируют элементы в списке.

В качестве общего примера возьмём сортировку чисел в порядке возрастания. Но эти методы можно легко адаптировать под ваши потребности.

Пузырьковая сортировка

Этот простой алгоритм выполняет итерации по списку, сравнивая элементы попарно и меняя их местами, пока более крупные элементы не «всплывут» в начало списка, а более мелкие не останутся на «дне».

Алгоритм

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

При достижении конца списка процесс повторяется заново для каждого элемента. Это крайне неэффективно, если в массиве нужно сделать, например, только один обмен. Алгоритм повторяется n² раз, даже если список уже отсортирован.

Для оптимизации алгоритма нужно знать, когда его остановить, то есть когда список отсортирован.

Чтобы остановить алгоритм по окончании сортировки, нужно ввести переменную-флаг. Когда значения меняются местами, устанавливаем флаг в значение True , чтобы повторить процесс сортировки. Если перестановок не произошло, флаг остаётся False и алгоритм останавливается.

Реализация

def bubble_sort(nums): # Устанавливаем swapped в True, чтобы цикл запустился хотя бы один раз swapped = True while swapped: swapped = False for i in range(len(nums) - 1): if nums[i] > nums[i + 1]: # Меняем элементы nums[i], nums[i + 1] = nums[i + 1], nums[i] # Устанавливаем swapped в True для следующей итерации swapped = True # Проверяем, что оно работает random_list_of_nums = [5, 2, 1, 8, 4] bubble_sort(random_list_of_nums) print(random_list_of_nums) 

Алгоритм работает в цикле while и прерывается, когда элементы ни разу не меняются местами. Вначале присваиваем swapped значение True , чтобы алгоритм запустился хотя бы один раз.

Время сортировки

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

Оценка сложности алгоритмов, или Что такое О(log n)

Сортировка выборкой

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

Алгоритм

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

Теперь, когда нам известно, что первый элемент списка отсортирован, находим наименьший элемент из оставшихся и меняем местами со вторым. Повторяем это до тех пор, пока не останется последний элемент в списке.

Реализация

def selection_sort(nums): # Значение i соответствует кол-ву отсортированных значений for i in range(len(nums)): # Исходно считаем наименьшим первый элемент lowest_value_index = i # Этот цикл перебирает несортированные элементы for j in range(i + 1, len(nums)): if nums[j] < nums[lowest_value_index]: lowest_value_index = j # Самый маленький элемент меняем с первым в списке nums[i], nums[lowest_value_index] = nums[lowest_value_index], nums[i] # Проверяем, что оно работает random_list_of_nums = [12, 8, 3, 20, 11] selection_sort(random_list_of_nums) print(random_list_of_nums)

По мере увеличения значения i нужно проверять меньше элементов.

Время сортировки

Затраты времени на сортировку выборкой в среднем составляют O(n²), где n — количество элементов списка.

Сортировка вставками

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

Алгоритм

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

Переходя к другим элементам несортированного сегмента, перемещаем более крупные элементы в отсортированном сегменте вверх по списку, пока не встретим элемент меньше x или не дойдём до конца списка. В первом случае x помещается на правильную позицию.

Реализация

def insertion_sort(nums): # Сортировку начинаем со второго элемента, т.к. считается, что первый элемент уже отсортирован for i in range(1, len(nums)): item_to_insert = nums[i] # Сохраняем ссылку на индекс предыдущего элемента j = i - 1 # Элементы отсортированного сегмента перемещаем вперёд, если они больше # элемента для вставки while j >= 0 and nums[j] > item_to_insert: nums[j + 1] = nums[j] j -= 1 # Вставляем элемент nums[j + 1] = item_to_insert # Проверяем, что оно работает random_list_of_nums = [9, 1, 15, 28, 6] insertion_sort(random_list_of_nums) print(random_list_of_nums) 

Время сортировки

Время сортировки вставками в среднем равно O(n²), где n — количество элементов списка.

Пирамидальная сортировка

Также известна как сортировка кучей. Этот популярный алгоритм, как и сортировки вставками или выборкой, сегментирует список на две части: отсортированную и неотсортированную. Алгоритм преобразует второй сегмент списка в структуру данных «куча» (heap), чтобы можно было эффективно определить самый большой элемент.

Алгоритм

Сначала преобразуем список в Max Heap — бинарное дерево, где самый большой элемент является вершиной дерева. Затем помещаем этот элемент в конец списка. После перестраиваем Max Heap и снова помещаем новый наибольший элемент уже перед последним элементом в списке.

Этот процесс построения кучи повторяется, пока все вершины дерева не будут удалены.

Реализация

Создадим вспомогательную функцию heapify() для реализации этого алгоритма:

def heapify(nums, heap_size, root_index): # Индекс наибольшего элемента считаем корневым индексом largest = root_index left_child = (2 * root_index) + 1 right_child = (2 * root_index) + 2 # Если левый потомок корня — допустимый индекс, а элемент больше, # чем текущий наибольший, обновляем наибольший элемент if left_child < heap_size and nums[left_child] >nums[largest]: largest = left_child # То же самое для правого потомка корня if right_child < heap_size and nums[right_child] >nums[largest]: largest = right_child # Если наибольший элемент больше не корневой, они меняются местами if largest != root_index: nums[root_index], nums[largest] = nums[largest], nums[root_index] # Heapify the new root element to ensure it's the largest heapify(nums, heap_size, largest) def heap_sort(nums): n = len(nums) # Создаём Max Heap из списка # Второй аргумент означает остановку алгоритма перед элементом -1, т.е. # перед первым элементом списка # 3-й аргумент означает повторный проход по списку в обратном направлении, # уменьшая счётчик i на 1 for i in range(n, -1, -1): heapify(nums, n, i) # Перемещаем корень Max Heap в конец списка for i in range(n - 1, 0, -1): nums[i], nums[0] = nums[0], nums[i] heapify(nums, i, 0) # Проверяем, что оно работает random_list_of_nums = [35, 12, 43, 8, 51] heap_sort(random_list_of_nums) print(random_list_of_nums) 

Время сортировки

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

Сортировка слиянием

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

Соседние элементы становятся отсортированными парами. Затем эти пары объединяются и сортируются с другими парами. Этот процесс продолжается до тех пор, пока не отсортируются все элементы.

Алгоритм

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

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

Реализация

def merge(left_list, right_list): sorted_list = [] left_list_index = right_list_index = 0 # Длина списков часто используется, поэтому создадим переменные для удобства left_list_length, right_list_length = len(left_list), len(right_list) for _ in range(left_list_length + right_list_length): if left_list_index < left_list_length and right_list_index < right_list_length: # Сравниваем первые элементы в начале каждого списка # Если первый элемент левого подсписка меньше, добавляем его # в отсортированный массив if left_list[left_list_index] 

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

Время сортировки

В среднем время сортировки слиянием составляет O(n log n).

Быстрая сортировка

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

Алгоритм

Быстрая сортировка начинается с разбиения списка и выбора одного из элементов в качестве опорного. А всё остальное передвигаем так, чтобы этот элемент встал на своё место. Все элементы меньше него перемещаются влево, а равные и большие элементы перемещаются вправо.

Реализация

Существует много вариаций данного метода. Способ разбиения массива, рассмотренный здесь, соответствует схеме Хоара (создателя данного алгоритма).

def partition(nums, low, high): # Выбираем средний элемент в качестве опорного # Также возможен выбор первого, последнего # или произвольного элементов в качестве опорного pivot = nums[(low + high) // 2] i = low - 1 j = high + 1 while True: i += 1 while nums[i] < pivot: i += 1 j -= 1 while nums[j] >pivot: j -= 1 if i >= j: return j # Если элемент с индексом i (слева от опорного) больше, чем # элемент с индексом j (справа от опорного), меняем их местами nums[i], nums[j] = nums[j], nums[i] def quick_sort(nums): # Создадим вспомогательную функцию, которая вызывается рекурсивно def _quick_sort(items, low, high): if low < high: # This is the index after the pivot, where our lists are split split_index = partition(items, low, high) _quick_sort(items, low, split_index) _quick_sort(items, split_index + 1, high) _quick_sort(nums, 0, len(nums) - 1) # Проверяем, что оно работает random_list_of_nums = [22, 5, 1, 18, 99] quick_sort(random_list_of_nums) print(random_list_of_nums)

Время выполнения

В среднем время выполнения быстрой сортировки составляет O(n log n).

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

Встроенные функции сортировки на Python

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

Отсортировать содержимое списка можно с помощью стандартного метода sort() :

>>> apples_eaten_a_day = [2, 1, 1, 3, 1, 2, 2] >>> apples_eaten_a_day.sort() >>> apples_eaten_a_day [1, 1, 1, 2, 2, 2, 3] 

Или можно использовать функцию sorted() для создания нового отсортированного списка, оставив входной список нетронутым:

>>> apples_eaten_a_day_2 = [2, 1, 1, 3, 1, 2, 2] >>> sorted_apples = sorted(apples_eaten_a_day_2) >>> sorted_apples [1, 1, 1, 2, 2, 2, 3] 

Оба эти метода сортируют в порядке возрастания, но можно изменить порядок, установив для флага reverse значение True :

# Обратная сортировка списка на месте >>> apples_eaten_a_day.sort(reverse=True) >>> apples_eaten_a_day [3, 2, 2, 2, 1, 1, 1] # Обратная сортировка, чтобы получить новый список >>> sorted_apples_desc = sorted(apples_eaten_a_day_2, reverse=True) >>> sorted_apples_desc [3, 2, 2, 2, 1, 1, 1] 

В отличие от других алгоритмов, обе функции в Python могут сортировать также списки кортежей и классов. Функция sorted() может сортировать любую последовательность, которая включает списки, строки, кортежи, словари, наборы и пользовательские итераторы, которые вы можете создать.

Функции в Python реализуют алгоритм Tim Sort, основанный на сортировке слиянием и сортировке вставкой.

Сравнение скоростей сортировок

Для сравнения сгенерируем массив из 5000 чисел от 0 до 1000. Затем определим время, необходимое для завершения каждого алгоритма. Повторим каждый метод 10 раз, чтобы можно было более точно установить, насколько каждый из них производителен.

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

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

Сортировки — квадратичные и сортировка слиянием¶

Мы считаем, что вы уже знаете и умеете следующие вещи:

  • основы языков Python, C++ или Java (примеры в конспектах будут чаще всего на питоне)
  • оператор if
  • циклы for и while
  • создание функций
  • концепцию рекурсии
  • поиск минимума в массиве

Квадратичные сортировки¶

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

А именно мы хотим написать такую функцию sort_array , которая принимает массив в качестве аргумента и сортирует его элементы:

def sort_array(array): # надо придумать, что написать здесь array = [1, -3, 7, 88, 7] sort_array(array) print(array) 
[1, -3, 7, 88, 7]

Задание¶

Какие вы знаете алгоритмы сортировки?

Если вы не знаете ни одного алгоритма, то придумайте какой-нибудь разумный алгоритм сами.

Сортировка пузырьком¶

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

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

Заметьте, как каждую итерацию максимальный элемент "всплывает как пузырек" к концу массива.

def bubble_sort(array): n = len(array) # длина массива for i in range(n): # n раз выполняем цикл for j in range(n - 1): # проходимся по всем элементам кроме последнего if array[j] > array[j + 1]: # сравниваем элемент по следующим a[j], a[j + 1] = a[j + 1], a[j] # меняем местами, если следующий меньше a = [1, -3, 7, 88, 7] bubble_sort(a) print(a) 
[-3, 1, 7, 7, 88]

Заметьте, что после $i$ шагов алгоритма сортировки пузырьком последние $i + 1$ чисел всегда отсортированы. Именно поэтому алгоритм и работает.

И именно поэтому его можно немного ускорить.

Задание¶

Подумайте, какие лишние элементы мы перебираем. Как нужно изменить границы в двух циклах for, чтобы не делать никаких бесполезных действий?

Сортировка выбором¶

Более понятным и придумываемым способом является сортировка выбором минимума (или максимума).

Чтобы отсортировать массив, нужно просто $N$ раз выбрать минимум среди еще неотсортированных чисел. То есть на $i$-ом шаге ищется минимум на отрезке $[i, n - 1]$, и этот минимум меняется с $i$-ым элементом, теперь отрезок $[0, i]$ отсортирован.

Сортировка вставками¶

Также существует сортировка вставками.

Префиксом длины $i$ будем называть первые $i$ элементов массива.

Тогда пусть на $i$-ом шаге у нас уже будет отсортирован префикс до $i$-го элемента. Чтобы этот префикс увеличить, нужно взять элемент, идущий после него, и менять с левым соседом, пока этот элемент наконец не окажется больше своего левого соседа. Если в конце он больше левого соседа, но меньше правого - это значит, что мы правильно вставили этот элемент в отсортированную часть массива.

Задание¶

Сдайте 4 первые задачи в контесте:

  1. Напишите сортировку пузырьком.
  2. Напишите сортировку выбором максимума.
  3. Напишите сортировку вставками.
  4. Выберите любой алгоритм и примените его для сортировки пар.

При сдаче задач нельзя пользоваться встроенной сортировкой!

Сортировка подсчетом¶

Предыдущие три алгоритма работали с массивами, в которых лежат абсолютно любые объекты, которые можно сравнивать. Любые числа, строки, пары, другие массивы, почти все что угодно.

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

Пусть, например, нам гарантируется, что все числа натуральные и лежат в промежутке от 1 до 100.

Тогда есть такой простой алгоритм: создадим массив размера $100$, в котором будем хранить на $i$-ом месте, сколько раз число $i$ встретилось в этом массиве. Пройдемся по всем числам, и увеличим соответствующее значение массива на $1$. Таким образом мы подсчитали, сколько раз какое число встретилось. Теперь можно просто пройтись по этому массиву и вывести $1$ столько раз, сколько раз встретилась $1$, вывести $2$ столько раз, сколько встретилась $2$, и так далее.

Задание¶

Сдайте 5, 6 и 7 задачи в контесте:

  1. Напишите сортировку подсчетом.
  2. Придумайте, как преобразовать сортировку подсчетом, чтобы она работала быстро.
  3. Придумайте, как использовать идею сортировки подсчетом в этой задаче.

При сдаче задач нельзя пользоваться встроенной сортировкой!

О-нотация¶

Очень часто требуется оценить, сколько времени работают эти алгоритмы. Но тут возникают проблемы:

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

Зачастую основной задачей программиста становится оптимизировать алгоритм, выполнение которого займёт тысячи лет, до какого-нибудь адекватного времени работы. Поэтому хотелось бы уметь предсказывать, сколько времени займёт выполнение алгоритма ещё до того, как мы его запустим.

Для этого давайте для начала попробуем оценить число операций в алгоритме.

Возникает вопрос: какие именно операции считать. Можно считать любые элементарные операции:

  • арифметические операции с числами: +, -, *, /
  • сравнение чисел: , =, ==, !=
  • присваивание: a[0] = 3

При этом надо учитывать, как реализованы некоторые отдельные вещи в самом языке. Например, в питоне срезы массива ( array[3:10] ) копируют этот массив, то есть этот срез работает за 7 элементарных действий. А swap , например, может работать за 3 присваивания.

Задание¶

Попробуйте посчитать точное число сравнений в сортировках пузырьком, выбором, вставками и подсчетом в худшем случае (это должна быть какая формула, зависящая от $N$ - длины массива). Для сортировки подсчетом давайте считать, что все числа целые и лежат в промежутке от 1 до $M$

И также посчитайте точное число присваиваний в сортировках пузырьком, выбором, вставками и подсчетом в худшем случае. Давайте считать, что swap — это 3 присваивания.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *