undefined

Алгоритмы сортировки. Сортировка вставками

Harvard CS50
3 уровень , 10 лекция
Доступна

Внимание! Практически весь материал этой лекции был в видеолекции.

class=»embed-responsive-item»



Если вы всё хорошо усвоили, просто пробегитесь глазами и переходите дальше.

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

Алгоритмы сортировки. Сортировка вставками - 1

Давайте на примере ниже разберем, как работает сортировка вставкой. До того, как мы начали, все элементы считаются неотсортированными.

Алгоритмы сортировки. Сортировка вставками - 2

Шаг 1. Возьмем первое неотсортированное значение (3) и вставим его в отсортированный подмассив. На этом шаге весь отсортированный подмассив, его начало и конец и будут этой самой тройкой.

Алгоритмы сортировки. Сортировка вставками - 3


Шаг 2.
 Поскольку 3 < 5, мы вставим 5 в отсортированный подмассив справа от 3.

Алгоритмы сортировки. Сортировка вставками - 4

Шаг 3. Теперь работаем над вставкой числа 2 в наш отсортированный массив. Сравниваем 2 со значениями справа налево, чтобы найти правильную позицию. Поскольку 2 < 5 и 2 < 3 и мы дошли до начала отсортированного подмассива. Следовательно, мы должны вставить 2 слева от 3. Для этого подвигаем 3 и 5 вправо, чтобы появилось место для двойки и вставляем её в начало массива.

Алгоритмы сортировки. Сортировка вставками - 5

Шаг 4. Нам повезло: 6 > 5, поэтому мы можем вставить это число сразу за числом 5.

Алгоритмы сортировки. Сортировка вставками - 6


Шаг 5.
4 < 6 и 4 < 5, но 4 > 3. Следовательно, мы знаем, что 4 нужно вставить справа от 3.

Снова мы вынуждены подвинуть 5 и 6 вправо, чтобы создать лакуну для 4. 

Алгоритмы сортировки. Сортировка вставками - 7

Готово!

Обобщенный алгоритм:

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

  1. Определить место в отсортированной части массива, куда нужно вставить n
  2. Сдвинуть отсортированные элементы вправо, чтобы сделать лакуну для n
  3. Вставить n в образовавшуюся лакуну в отсортированной части массива.

А вот и код! Рекомендуем написать свою версию программы сортировки. 

Алгоритмы сортировки. Сортировка вставками - 8

Асимптотическая сложность алгоритма

В самом плохом случае мы сделаем одно сравнение со вторым элементом, два сравнения с третьим и так далее. Таким образом, наша скорость равна O(n2).

В лучшем случае мы будем работать с уже отсортированным массивом. Отсортированная часть, которую мы строим слева направо без вставок и передвижений элементов займет время Ω(n).

Комментарии (11)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Эдик Марруго Уровень 0
16 ноября 2020
#include <stdio.h> #include <stdlib.h> #define SIZE 10 void sort(int* mas, int size); void fillArray(int* mas, int size); void printArray(int* mas, int size); int checkIfSorted(int* mas, int size); int main() { int mas[SIZE]; fillArray(mas, SIZE); printArray(mas, SIZE); sort(mas, SIZE); printArray(mas, SIZE); checkIfSorted(mas, SIZE); } void fillArray(int* mas, int size) { for (int i = 0; i < size; i++) { mas[i] = (rand() % 100); } } void printArray(int* mas, int size) { for (int i = 0; i < size; i++) { printf("%i\n" , mas[i]); } printf("\n"); } void sort(int* mas, int size) { int temp = 0; for (int i = 0; i < size; i++) { int n = i; while (n > 0 && (mas[n - 1] > mas[n])) { temp = mas[n]; mas[n] = mas[n - 1]; mas[n - 1] = temp; n--; } } } int checkIfSorted(int* mas, int size) { for (int i = 0; i < (size - 1); i++) { if (mas[i] > mas[i + 1]) { printf("Array dont sorted"); return 0; } } printf("Array sorted"); return 1; }
Ихтияр Кадыров Уровень 1 Шымкент Казахстан
1 ноября 2020

/**
 * Производит сортировку в массиве
 * haystack согласно алгоритму 
 * сортировки вставкой.
 * 
 * @param haystack [Сортируемый массив]
 * @param size     [Длина массива]
 */
void insertion_sort (int haystack[], const size_t size)
{

	size_t j;
	int key;

	for (size_t i = 0; i < size; i++)
	{
		if (i > 0 && haystack[i] < haystack[i - 1])
		{
			j = i;
			key = haystack[i];
			
			while (j > 0 && key < haystack[j - 1])
			{
				haystack[j] = haystack[j - 1];
				j--;
			}

			haystack[j] = key;
		}
	}

}
Серега Уровень 19 Кривой Рог Украина
29 августа 2020
https://www.youtube.com/playlist?list=PLyApprAtr5yjywFgRkxhfGfesgYoIhU8U
Михаил Уровень 1 Харьков
30 июля 2020

/*Прогрмамма для сортировки вставками*/
#include <stdio.h>
#include <cs50.h>    //get_string
#include <string.h>  //strlen
int main(void)
{
    int i, n, j, e;
    string s = get_string("Введите ряд позитивных чисел:\n");
    for(i = 0, n = strlen(s); i < n; i++)
    {
        e = s[i];       //e - элемент, для сравнения чисел
        j = i;

    while(j > 0 && s[j - 1] > e)   //цикл для того, чтобы 1е число не трогать и сравнивать предыдущие число с последующим...
    {
      s[j] = s[j - 1];      //...если предыдущее больше последующего, то меняем их местами
      j = j - 1;
      s[j] = e;
    }
    }
    printf("%s", s);
    printf("\n");
    return 0;
}
Андрей Уровень 0
4 мая 2020
Вот моё решение. #include <stdio.h> #include <cs50.h> int main (){ int n = get_int ("Введите длину массива: "); float a[n]; for (int i = 0; i < n; i++){ printf ("Введите число %d: ", i+1); scanf ("%f", &a[i]); } for (int i = 0; i < n; i ++){ float element = a[i]; int j = i; while (j > 0 && a[j-1] > element){ a[j] = a[j-1]; j = j - 1; a[j] = element; } } printf ("Отсортированный по возрастанию цикл: "); for (int i = 0; i < n; i++){ printf("%.2f, ", a[i]); } printf("\n"); return 0; }
Danil Lomakin Уровень 2
24 октября 2019

#include <stdio.h>

void printArr(int array[], int n);
void sortArr(int array[], int n);

int main(void) {
    const int n = 13;
    int array[13] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3};

    printArr(array, n);
    sortArr(array, n);
    printArr(array, n);
}

void printArr(int array[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%i ", array[i]);
    }
    printf("\n");
}

void sortArr(int array[], int n) {
    int temp;

    for (int i = 1; i < n; i++) {
        for (int j = i; j > 0 && array[j] < array[j - 1]; j--) {
            // swaping.
            temp = array[j];
            array[j] = array[j - 1];
            array[j - 1] = temp;
        }
    }
}
Светлана Уровень 12
15 июля 2019
В самом начале ссылка приводит не на ту видеолекцию.
Александр Уровень 24 Рыбинск Россия
11 ноября 2017
Сдвинуть отсортированные элементы вправо, чтобы сделать лакуну для n Вставить n в образовавшуюся лакуну в отсортированной части массива. ******* По мне слово "лакуна" нужно заменить на более распространенное, ни к чему оно тут)
mrz Уровень 0
7 ноября 2017
Исправьте ошибку в строке "Шаг 2. Поскольку 3 > 5...". https://pastebin.com/75vuGvDM - это правильный вариант реализации алгоритма? Поделитесь своими.
Александр Уровень 0
14 октября 2017
Может я чего-то не понял, но приведённый код какой-то странный: На первом шаге выходит:

element = array[0]
j = i = 0
Следующая строка теряет смысл:

While (0 > 0 and array [-1] > element)