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

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск
Сортировка вставками
Пример сортировки вставками

Пример сортировки вставками
Предназначение

Алгоритм сортировки

Структура данных

Массив

Худшее время

О(n2) сравнений, обменов

Лучшее время

O(n) сравнений, O(1) обмен

Среднее время

О(n2) сравнений, обменов

Затраты памяти

О(n) всего, O(1) вспомогательный

Сортировка вставками (англ. Insertion sort) — алгоритм сортировки, в котором элементы входной последовательности просматриваются по одному, и каждый новый поступивший элемент размещается в подходящее место среди ранее упорядоченных элементов[1]. Вычислительная сложность - O(n^2).

Описание[править | править вики-текст]

Пример сортировки вставками

На вход алгоритма подаётся последовательность n чисел: a_1, a_2, ..., a_n. Сортируемые числа также называют ключами. Входная последовательность на практике представляется в виде массива с n элементами. На выходе алгоритм должен вернуть перестановку исходной последовательности a_{1}^{'}, a_{2}^{'}, ..., a_{n}^{'}, чтобы выполнялось следующее соотношение a_{1}^{'} \leqslant a_{2}^{'} \leqslant ... \leqslant a_{n}^{'}[2]

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

Данный алгоритм можно ускорить при помощи использования бинарного поиска для нахождения места текущему элементу в отсортированной части. Проблема с долгим сдвигом массива вправо решается при помощи смены указателей[4].

Псевдокод[править | править вики-текст]

На вход процедуре сортировки подаётся массив A[1..n], состоящий из элементов последовательности A[1], A[2], ..., A[n], которые требуется отсортировать. A.length — размер исходного массива. Для сортировки не требуется привлечения дополнительной памяти, кроме постоянной величины для одного элемента, так как выполняется перестановка в пределах массива. В результате работы процедуры во входном массиве оказывается требуемая выходная последовательность элементов[5]:

for j = 2 to A.length  
    key = A[j]
    i = j - 1
    while i > 0 and A[i] > key
         A[i+1] = A[i]
         i = i - 1
    A[i+1] = key

Анализ алгоритма[править | править вики-текст]

Время выполнения алгоритма зависит от входных данных: чем большее множество нужно отсортировать, тем большее время потребуется для выполнения сортировки. Также на время выполнения влияет исходная упорядоченность массива. Время работы алгоритма для различных входных данных одинакового размера зависит от элементарных операций, или шагов, которые потребуется выполнить[6].

Для каждой инструкции алгоритма введём временную стоимость и количество повторений, где t_j — количесво проверок условия во внутреннем цикле while[7]:

Код Стоимость Повторы
for j = 2 to A.length c_1 n
key = A[j] c_2 n-1
i = j — 1 c_3 n-1
while i > 0 and A[i] > key c_4 \sum_{j=2}^n t_j
A[i+1] = A[i] c_5 \sum_{j=2}^n (t_j-1)
i = i — 1 c_6 \sum_{j=2}^n (t_j-1)
A[i+1] = key c_7 n-1

Время работы алгоритма сортировки вставками — это сумма времён работы каждого шага[8]: T(n)=c_1n+c_2(n-1)+c_3(n-1)+c_4\sum_{j=2}^n t_j+c_5\sum_{j=2}^n (t_j-1)+c_6\sum_{j=2}^n (t_j-1)+c_7(n-1).

Самым благоприятным случаем является отсортированный массив. При этом все внутренние циклы состоят всего из одной итерации, то есть t_j=1 для всех j. Тогда время работы алгоритма составит T(n)=(c_1+c_2+c_3+c_4+c_7)n-(c_1+c_2+c_3+c_4+c_7)=O(n). Время работы линейно от размера входных данных[9].

Анализ наихудшего случая[править | править вики-текст]

Наихудшим случаем является массив, отсортированный в порядке, обратном нужному. При этом каждый новый элемент сравнивается со всеми в отсортированной последовательности. Это означает, что все внутренние циклы состоят из j итераций, то есть t_j=j для всех j. Тогда время работы алгоритма составит:

T(n)=c_1n+c_2(n-1)+c_3(n-1)+c_4\sum_{j=2}^n j+c_5\sum_{j=2}^n (j-1)+c_6\sum_{j=2}^n (j-1)+c_7(n-1)

T(n)=c_1n+c_2(n-1)+c_3(n-1)+c_4(\frac{n(n+1)}{2}-1)+c_5\frac{n(n-1)}{2}+c_6\frac{n(n-1)}{2}+c_7(n-1)=O(n^2).

Время работы является квадратичной функцией от размера входных данных[10].

Анализ среднего случая[править | править вики-текст]

Для анализа среднего случая нужно посчитать среднее число сравнений, необходимых для определения положения очередного элемента. При добавлении нового элемента потребуется, как минимум, одно сравнение, даже если этот элемент оказался в правильной позиции. i-й добавляемый элемент может занимать одно из i+1 положений. Предполагая случайные входные данные, новый элемент равновероятно может оказаться в любой позиции[11]. Среднее число сравнений для вставки i-го элемента[12]:

T_i=\frac{1}{i+1}(\sum_{p=1}^i p+i)=\frac{1}{i+1}(\frac{i(i+1)}{2}+1)=\frac{i}{2}+1-\frac{1}{i+1}

Для оценки среднего времени работы для n элементов нужно просуммировать[13]:

T(n)=\sum_{i=1}^{n-1} T_i=\sum_{i=1}^{n-1} (\frac{i}{2}+1-\frac{1}{i+1})=\sum_{i=1}^{n-1} \frac{i}{2}+\sum_{i=1}^{n-1} 1-\sum_{i=1}^{n-1} \frac{1}{i+1})

T(n)\approx\frac{n^2-n}{4}+(n-1)-(ln(n)-1)=O(n^2)

Временная сложность алгоритма — O(n^2). Однако, из-за константных множителей и членов более низкого порядка алгоритм с более высоким порядком роста может выполняться для небольших входных данных быстрее, чем алгоритм с более низким порядком роста[14].

Плюсы:

  • эффективен на небольших наборах данных, на наборах данных до десятков элементов может оказаться лучшим;
  • эффективен на наборах данных, которые уже частично отсортированы;
  • это устойчивый алгоритм сортировки (не меняет порядок элементов, которые уже отсортированы);
  • может сортировать список по мере его получения;
  • использует O(1) временной памяти, включая стек.
  • может работать значительно быстрее за счёт бинарного поиска

Минусы:

См. также[править | править вики-текст]

Примечания[править | править вики-текст]

  1. Кнут Д. Э. 5.2 Внутренняя сортировка // Искусство программирования. Том 3. Сортировка и поиск = The Art of Computer Programming. Volume 3. Sorting and Searching / Под ред. Ю. В. Козаченко. — 2. — М.: Вильямс, 2001. — Т. 3. — 800 с.
  2. CLRS, 2013, p. 38
  3. CLRS, 2013, p. 39
  4. Кнут Д. Э. 5.2.1 Сортировка путем вставок // Искусство программирования. Том 3. Сортировка и поиск = The Art of Computer Programming. Volume 3. Sorting and Searching / Под ред. Ю. В. Козаченко. — 2. — М.: Вильямс, 2001. — Т. 3. — 800 с.
  5. CLRS, 2013, p. 39-40
  6. CLRS, 2013, p. 47
  7. CLRS, 2013, p. 48
  8. CLRS, 2013, p. 48-49
  9. CLRS, 2013, p. 49
  10. CLRS, 2013, p. 49-50
  11. Макконнелл, 2004, p. 74
  12. Макконнелл, 2004, p. 75
  13. Макконнелл, 2004, p. 75-76
  14. CLRS, 2013, p. 51

Литература[править | править вики-текст]

  • Ахо А. В., Хопкрофт Д. Э., Ульман Д. Д. Структуры данных и алгоритмы = Data structures and algorithms / Под ред. А. А. Минько. — М.: Вильямс, 2000. — С. 231. — ISBN 5-8459-0122-7.
  • Кнут Д. Э. 5.2.1 Сортировка путем вставок // Искусство программирования. Том 3. Сортировка и поиск = The Art of Computer Programming. Volume 3. Sorting and Searching / Под ред. Ю. В. Козаченко. — 2. — М.: Вильямс, 2001. — Т. 3. — 800 с.
  • Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн, К. 2.1. Сортировка вставкой // Алгоритмы: построение и анализ = Introduction to Algorithms / Под ред. И. В. Красикова. — 3-е изд. — М.: Вильямс, 2013. — С. 38-45. — ISBN 5-8459-1794-8.
  • Макконнелл Дж. Основы современных алгоритмов = Analysis of Algorithms: An Active Learning Approach / Под ред. С. К. Ландо. — М.: Техносфера, 2004. — С. 72-76. — ISBN 5-94836-005-9.

Ссылки[править | править вики-текст]