Сортировка Вставками (Insertion-sort)
- Подробности
- Категория: Сортировка и поиск
Сортировка вставками – простой алгоритм сортировки, преимущественно использующийся в учебном программировании. К положительной стороне метода относится простота реализации, а также его эффективность на частично упорядоченных последовательностях, и/или состоящих из небольшого числа элементов. Тем не менее, высокая вычислительная сложность не позволяет рекомендовать алгоритм в повсеместном использовании.
На каждом шаге алгоритма мы выбираем один из элементов входных данных и вставляем его на нужную позицию в уже отсортированном списке до тех пор, пока набор входных данных не будет исчерпан. Метод выбора очередного элемента из исходного массива произволен; может использоваться практически любой алгоритм выбора. Обычно (и с целью получения устойчивого алгоритма сортировки), элементы вставляются по порядку их появления во входном массиве.
| Худшее время |
О(n2) сравнений, обменов |
|---|---|
| Лучшее время |
O(n) сравнений, O(1) обмен |
| Среднее время |
О(n2) сравнений, обменов |
| Затраты памяти |
О(n) всего, O(1) вспомогательный |
Реализация алгоритма на различных языках программирования:
Haskell
insert :: Ord a ? a ? [a] ? [a] insert x [] = [x] insert x (y : ys) | x ? y = x : y : ys | otherwise = y : insert x ys isort :: Ord a ? [a] ? [a] isort [ ] = [ ] isort (x : xs) = insert x (isort xs)
Си
int i, j, temp;
for (i = 1; i < size; i++)
{
temp = array[i];
for (j = i - 1; j >= 0; j--)
{
if (array[j] < temp)
break;
array[j + 1] = array[j];
array[j] = temp;
}
}
C++
#include <algorithm>
template <typename Iterator>
void insertion_sort(Iterator first, Iterator last)
{
if (!(first < last))
return;
for (Iterator i = first + 1; i != last; ++i)
for (Iterator j = i; j != first && *j < *(j - 1); --j)
std::iter_swap(j - 1, j);
}
C++ (оптимизирован)
Произведены следующие оптимизации:
- нахождение минимального элемента и помещение его в первую позицию (это требуется для правильного функционирования второго пункта);
- выход из внутреннего цикла, когда элемент находится на требуемой позиции;
- замена операции обмена (swap) операцией присваивания.
template <typename Item>
void exch(Item &A, Item &B)
{
Item t = A; A = B; B = t;
}
template <typename Item>
void compexch(Item &A, Item &B)
{
if (B < A) exch(A, B);
}
template <typename Item>
void insertion_sort(Item a[], int L, int R)
{
for(int i = R; i > L; i--)
compexch(a[i - 1], a[i]);
for (int i = L + 2; i <= R; i++)
{
int j = i;
Item cur = a[j];
while (a[j - 1] > cur)
{
a[j] = a[j - 1];
j--;
}
a[j] = cur;
}
}
C# (с возвратом результата)
public int[] InsertionSort(int[] array)
{
int[] result = new int[array.Length];
for (int i = 0; i < array.Length; i++)
{
int j = i;
while (j > 0 && result[j - 1] > array[i])
{
result[j] = result[j - 1];
j--;
}
result[j] = array[i];
}
return result;
}
C# (без дополнительной памяти 1)
public void InsertionSort(int[] array)
{
for (int i = 1; i < array.Length; i++)
{
int cur = array[i];
int j = i;
while (j > 0 && cur < array[j - 1])
{
array[j] = array[j - 1];
j--;
}
array[j] = cur;
}
}
C# (без дополнительной памяти 2)
public void InsertionSort(int[] array)
{
for (int i = 1; i < array.Length; i++)
{
int j;
int buf = array[i];
for (j = i - 1; j >= 0; j--)
{
if (array[j] < buf)
break;
array[j + 1] = array[j];
}
array[j + 1] = buf;
}
}
Java 1
public static void insertionSort(int[] arr) {
for(int i = 1; i < arr.length; i++){
int currElem = arr[i];
int prevKey = i - 1;
while(prevKey >= 0 && arr[prevKey] > currElem){
arr[prevKey+1] = arr[prevKey];
arr[prevKey] = currElem;
prevKey--;
}
}
}
Java 2
public static void insertionSort2(int[] m, int a, int b) {
int t;
int i, j;
for (i = a; i < b; i++) {
t = m[i];
for (j = i - 1; j >= a && m[j] > t; j--)
m[j + 1] = m[j];
m[j + 1] = t;
}
}
Javascript
(function() {
var oSort= function() {
var that = {};
//собственно сама функция сортировки
that.insertionSort = function(a) {
var i,j,x,
iCount = that.getCountOfElements(a);
for( i=0; i<iCount; i++) {
x = a[i];
for( j=i-1; j>=0 && a[j]>x; j-- ) {
a[j+1] = a[j];
}
a[j+1] = x;
}
return a;
};
that.getCountOfElements = function(a) {
var i = 0,
elem;
for (elem in a) {
i++
}
return i;
};
return that;
}();
console.log(oSort.insertionSort([9, 13, 7, 12, 10, 14, 8, 11, 6]));
//[6, 7, 8, 9, 10, 11, 12, 13, 14]
})();
VBA
Sub Sort(Mus() As Long)
Dim l As Long, r As Long, i As Long, j As Long, buf As Long
l = LBound(Mus)
r = UBound(Mus)
For i = (l + 1) To r
buf = Mus(i)
j = i - 1
Do While (Mus(j) > buf)
Mus(j + 1) = Mus(j)
j = j - 1
If j < l Then Exit Do
Loop
Mus(j + 1) = buf
Next
End Sub
Python
def fast_insertion_sort(l):
for i in xrange(1, len(l)):
j = i - 1
value = l.pop(i)
while (j >= 0) and (l[j] > value):
j -= 1
l.insert(j + 1, value)
return l
Perl
for(1..$N-1){
my$tmp=$out[$_];
for($j=$_-1;$j>=0;$j--){
$out[$j+1]=$out[$j];
last if($out[$j]lt$tmp);
}
$out[$j+1]=$tmp;
}
Паскаль
const N = 255;
type TArray = array [1..N] of integer;
procedure InsertSort(var x: TArray);
var
i, j, buf: integer;
begin
for i := 2 to N do
begin
buf := x[i];
j := i - 1;
while (j >= 1) and (x[j] > buf) do
begin
x[j + 1] := x[j];
j := j - 1;
end;
x[j + 1] := buf;
end;
end;
Delphi
type TArray<T> = array of T;
procedure TSomeObject.InsertSort<T>(var arr: TArray<T>);
var
i, j: integer;
buf:T;
begin
for i := Low(arr)+1 to High(arr) do
begin
buf := arr[i];
j := i - 1;
while (j >= Low(arr) ) and (arr[j] > buf) do
begin
arr[j + 1] := arr[j];
Dec(j);
end;
arr[j + 1] := buf;
end;
end;
PHP
function insertion_sort(&$a) {
// для каждого $a[$i] начиная со второго элемента...
for ($i = 1; $i < count($a); $i++) {
$x = $a[$i];
for ($j = $i - 1; $j >= 0 && $a[$j] > $x; $j--) {
/* сдвигаем элементы вправо, пока выполняется условие
$a[$j] > $a[$i] */
$a[$j + 1] = $a[$j];
}
// на оставшееся после сдвига место, ставим $a[$i]
$a[$j + 1] = $x;
}
}
Ruby
arr = [9, 13, 7, 12, 10, 14, 8, 11, 6]
for i in 1..arr.length - 1
x = arr[i]
for j in 0..i - 1
if arr[i] < arr[j]
i.downto(j + 1) do |k|
arr[k] = arr[k - 1]
end
arr[j] = x
break
end
end
end
puts "#{arr.join(" ")}"
# output => 6 7 8 9 10 11 12 13 14
Turbo Basic 1.1
Входной массив Y[1],...,Y[N]
FOR I=2 TO N
K=Y[I]
J=I-1
WHILE J>0 AND Y[J]>K
Y[J+1]=Y[J]
J=J-1
WEND
Y[J+1]=K
NEXT I
Время выполнения алгоритма зависит от входных данных: чем большее множество нужно отсортировать, тем большее время выполняется сортировка. Также на время выполнения влияет исходная упорядоченность массива. Так, лучшим случаем является отсортированный массив, а худшим — массив, отсортированный в порядке, обратном нужному. Временная сложность алгоритма при худшем варианте входных данных — O(n^2).
При написании статьи были использованы открытые источники сети интернет :

