Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

11.1. Вид слияния 509

Рисунок 11.7: визуальный анализ времени дерева вида слияния T. Каждый узел показывают маркированный размером его подпроблемы.

11.1.4 C ++ внедрения вида слияния

В этом подразделе мы представляем два полных C ++ внедрения слияния -

алгоритм вида, один для списков и один для векторов. В обоих случаях объект компаратора (см. Раздел 8.1.2) используется, чтобы решить относительный заказ элементов. Вспомните, что компаратор - класс, который осуществляет меньше оператор, перегружая» ()» оператор. Например, учитывая компаратор возражают меньше, относительный тест x <y может

будьте осуществлены с меньше (x, y), и тест x£ y может быть осуществлен как! меньше (y, x).

Во-первых, в Кодовом Фрагменте 11.3, мы представляем C ++ внедрение основанного на списке

алгоритм вида слияния как рекурсивная функция mergeSort. Мы представляем каждую se-айву как список STL (Раздел 6.2.4). Процесс слияния свободно основан на алгоритме, представленном в Кодовом Фрагменте 11.2. Главная функция mergeSort выгодная партия - tions входной список S в два вспомогательных списка, S1 и S2, примерно равняется размерам. Они каждый сортированы рекурсивно, и результаты тогда объединены, призвав func-tion слияние. Слияние функции неоднократно перемещает меньший элемент этих двух списков S1 и S2 в список S продукции.

Функции из нашего списка, ADT, такой столь передний и insertBack, были заменены их эквивалентами STL, такой, как начинают и пододвигают обратно, соответственно. Доступ к элементам списка предусмотрен списком iterators. Учитывая iterator p, вспомните, что *p получает доступ к текущему элементу, и *p ++ получает доступ к текущему элементу, и incre-чеканит iterator к следующему элементу списка.

510

Глава 11. Сортировка, наборы и выбор

Каждый список изменен вставками и удалениями только в голове и хвосте; следовательно, каждое обновление списка берет O (1) время, принимая любое внедрение списка, основанное на вдвойне связанных списках (см. Таблицу 6.2). Для списка S размера n, функция mergeSort (S, c) пробеги вовремя O (n регистрируют n).

шаблон <typename E, typename C> //вид слияния S

пустота mergeSort (list<E>& S, константа C& меньше)

typedef typename список <E>:: iterator Itor;

интервал n = S.size (); если (n <= 1) возвращение; список <E> S1, S2; Itor p = S.begin ();

//последовательность элементов

//уже сортированный

для (интервал i = 0; я <n/2; я ++) S1.push назад (*p ++);//копируют первую половину к S1 для (интервал i = n/2; я <n; я ++) S2.push назад (*p ++);//копируют вторую половину к S2

S.clear (); //содержание ясного С mergeSort (S1, меньше); //повторяются на первой половине mergeSort (S2, меньше); //повторяются на второй половине слияния (S1, S2, S, меньше); //сливают S1 и S2 в S

шаблон <typename E, typename C> //сливают полезность

недействительное слияние (list<E>& S1, list<E>& S2, list<E>& S, константа C& меньше)

typedef typename список <E>:: iterator Itor; //последовательность элементов

Itor p1 = S1.begin (); Itor p2 = S2.begin ();

в то время как (p1! = S1.end () && p2! = S2.end ())

если (меньше (*p1, *p2))

S.push назад (*p1 ++);

еще

S.push назад (*p2 ++);

в то время как (p1! = S1.end ())

S.push назад (*p1 ++); в то время как (p2! = S2.end ())

S.push назад (*p2 ++);

//пока любой не пуст//, прилагают меньший к S

//отдых копии S1 к S

//отдых копии S2 к S

Кодовый Фрагмент 11.3: Функции mergeSort и слияние, осуществляющее основанное на списке

алгоритм вида слияния.

Затем, в Кодовом Фрагменте 11.4, мы представляем нерекурсивную основанную на векторе версию вида слияния, который также бежит в O (n, регистрируют n), время. Это немного быстрее, чем рекурсивный основанный на списке вид слияния на практике, поскольку это избегает дополнительных накладных расходов создания узла и рекурсивных вызовов. Главная идея состоит в том, чтобы выполнить вид слияния вверх дном, выполнив уровень уровнем слияний, повышающийся дерево вида слияния. Вход - вектор STL S.

Мы начинаем, сливая каждую странно-ровную пару элементов в сортированные пробеги длины