Сортировка слиянием использует подход разделяй и властвуй. Он делит массив элементов на два подмассива по n/2 элементов в каждом. Затем он сортирует два подмассива рекурсивно, используя сортировку слиянием. Затем эти подмассивы объединяются для создания единого отсортированного массива.

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

Выполнение

Вот общая реализация функций merge и merge_sort. Он сортирует массив всех типов данных.

template<class T>
void merge(std::vector<T>& v, int p, int q, int r)
{
    int size1 = q-p+1;
    int size2 = r-q;
    std::vector<T> L(size1);
    std::vector<T> R(size2);

    for(int i = 0; i < size1; i++)
    {
        L[i] = v[p+i];
    }
    for(int j = 0; j < size2; j++)
    {
        R[j]=v[q+j+1];
    }

    int i=0,j=0;
    int k;
    for(k = p; k <= r && i < size1 && j < size2; k++)
    {
        if(L[i] <= R[j])
        {
            v[k] = L[i];
            i++;
        }
        else
        {
            v[k] = R[j];
            j++;
        }
    }
    for(i = i; i < size1; ++i)
    {
        v[k] = L[i];
        k++;
    }

    for(j = j; j < size2; j++)
    {
        v[k] = R[j];
        k++;
    }
}

При вызове функции merge создаются два вспомогательных вектора L и R. L инициализируется элементами левого подмассива, а R инициализируется элементами правого подмассива. Оба подмассива содержат по одному элементу. Например. из приведенного выше рис. L содержит 5, а R содержит 2.

Когда мы объединяем эти подмассивы, выбирается наименьший элемент из этих подмассивов, и элемент вводится во входной массив v с индексом 0. k поддерживает индекс входного массива, а i и j поддерживает индексы L и R подмассива соответственно.

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

template<class T>
void merge_sort(std::vector<T>& v, int p, int r)
{
    if(p < r)
    {
        int q = (p+r)/2;
        merge_sort(v, p, q);
        merge_sort(v, q+1, r);
        merge(v, p, q, r);
    }
}

merge_sort рекурсивно вызывает себя до тех пор, пока r не станет меньше или равно p.

Вот результат сортировки слиянием с универсальными функциями.

C++ реализация сортировки слиянием

#include <iostream>
#include <vector>

template<class T>
void merge(std::vector<T>& v, int p, int q, int r)
{
    int size1 = q-p+1;
    int size2 = r-q;
    std::vector<T> L(size1);
    std::vector<T> R(size2);

    for(int i = 0; i < size1; i++)
    {
        L[i] = v[p+i];
    }
    for(int j = 0; j < size2; j++)
    {
        R[j]=v[q+j+1];
    }

    int i=0,j=0;
    int k;
    for(k = p; k <= r && i < size1 && j < size2; k++)
    {
        if(L[i] <= R[j])
        {
            v[k] = L[i];
            i++;
        }
        else
        {
            v[k] = R[j];
            j++;
        }
    }
    for(i = i; i < size1; ++i)
    {
        v[k] = L[i];
        k++;
    }

    for(j = j; j < size2; j++)
    {
        v[k] = R[j];
        k++;
    }
}

template<class T>
void merge_sort(std::vector<T>& v, int p, int r)
{
    if(p < r)
    {
        int q = (p+r)/2;
        merge_sort(v, p, q);
        merge_sort(v, q+1, r);
        merge(v, p, q, r);
    }
}

int main()
{
    std::vector<int>vec;
    vec.push_back(13);
    vec.push_back(5);
    vec.push_back(7);
    vec.push_back(7);
    vec.push_back(4);
    vec.push_back(2);
    vec.push_back(10);
    int sz = vec.size();
    std::cout << "Entered array : ";
    for(int n = 0; n < sz; n++)
    {
        std::cout << vec[n] <<" ";
    }
    std::cout << "\n";
    std::cout << "Sorted array : ";
    merge_sort(vec, 0, sz-1);
    for(int n = 0; n < sz; n++)
    {
        std::cout << vec[n] << " ";
    }
    std::cout << "\n\n";

    std::vector<char> c;
    c.push_back('d');
    c.push_back('y');
    c.push_back('h');
    c.push_back('l');
    c.push_back('e');
    c.push_back('a');
    int sz1 = c.size();
    std::cout << "Entered array : ";
    for(int n = 0; n < sz1; n++)
    {
        std::cout << c[n] <<" ";
    }
    std::cout << "\n";
    std::cout << "Sorted array : ";
    merge_sort(c, 0, sz1-1);
    for(int n = 0; n < sz1; n++)
    {
        std::cout << c[n] << " ";
    }
    std::cout << "\n\n";

    std::vector<std::string> str;
    str.push_back("car");
    str.push_back("dog");
    str.push_back("apple");
    str.push_back("ball");
    str.push_back("tree");
    int sz2 = str.size();

    std::cout << "Entered array : ";
    for(int n = 0; n < sz2; n++)
    {
        std::cout << str[n] <<" ";
    }
    std::cout << "\n";
    std::cout << "Sorted array : ";
    merge_sort(str, 0, sz2-1);
    for(int n = 0; n < sz2; n++)
    {
        std::cout << str[n] << " ";
    }
    std::cout << "\n";

    return 0;
}

Посмотреть этот код на Github

Ссылка:
Введение в алгоритмы
Руководство по проектированию алгоритмов
Простые структуры данных и алгоритмы
Справочник конкурентоспособного программиста — Антти Лааксонен

Вам также может понравиться

Сортировка выбором
Сортировка вставками
Быстрая сортировка
Сортировка пирамидой

Первоначально опубликовано на https://programmercave0.github.io 24 августа 2017 г.