Домашняя страница Простейшие алгоритмы сортировки
Публикация
Отменить

Простейшие алгоритмы сортировки

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

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

  • Сортировка вставками
  • Сортировка слиянием
  • Пузырьковая сортировка

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

Для генерации массива будем использовать следующий код:

1
2
3
4
std::vector< int > arr;
const int N = 10;
for ( int i = 0; i < N; ++i )
    arr.push_back( rand( ) % 10 );

для вывода результатов на экран

1
2
3
for ( int i = 0; i < N; ++i )
    std::cout << arr[ i ] << " ";
std::cout << std::endl;

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

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

Вот сам алгоритм

1
2
3
4
5
6
7
8
9
10
11
12
// insertion sort
for ( int j = 1; j < arr.size( ); ++j )
{
    int key = arr[ j ];
    int i = j - 1;
    while ( i >= 0 && arr[ i ] > key )
    {
        arr[ i + 1 ] = arr[ i ];
        i--;
    }
    arr[ i + 1 ] = key;
}

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

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

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

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

Функция слияния:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void merge( std::vector< int >& arr, int p, int q, int r )
{
    int n1 = q - p;
    int n2 = r - q;
    
    std::vector< int > left;
    left.resize( n1 + 1 );
    
    std::vector< int > right;
    right.resize( n2 + 1 );
    
    for ( int i = 0; i < n1; ++i )
        left[ i ] = arr[ p + i ];
    for ( int j = 0; j < n2; ++j )
        right[ j ] = arr[ q + j ];
    
    left[ n1 ] = 0x7fffffff; // +singularity
    right[ n2 ] = 0x7fffffff; // +singularity
    
    int i = 0, j = 0;
    for ( int k = p; k < r; ++k )
    {
        if ( left[ i ] <= right[ j ] )
        {
            arr[ k ] = left[ i ];
            i++;
        }
        else
        {
            arr[ k ] = right[ j ];
            j++;
        }
    }
}

Функция сортировки слиянием:

1
2
3
4
5
6
7
8
9
10
void merge_sort( std::vector< int >& arr, int p, int r )
{
    if ( p < ( r - 1 ) )
    {
        int q = ( p + r ) / 2;
        merge_sort( arr, p, q );
        merge_sort( arr, q, r );
        merge( arr, p, q, r );
    }
}

Ну и соответственно вызов нашей замечательной сортировки:

1
merge_sort( arr, 0,  arr.size( ) );

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

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

Вот ее код:

1
2
3
4
5
6
7
8
for ( int i = 0; i < arr.size( ) - 1; ++i )
{
    for ( int j = i; j < arr.size( ); ++j )
    {
        if ( arr[ i ] > arr[ j ] )
            std::swap( arr[ i ], arr[ j ] );
    }
}
Публикация защищена лицензией CC BY 4.0 .

Секреты книги для героев

Уралмаш, разваливающиеся жемчужины советской эпохи!