Основно съдържание
Компютърни науки
Курс: Компютърни науки > Раздел 1
Урок 8: Сортиране чрез сливане- Алгоритми "разделяй и владей"
- Преглед на сортиране чрез сливане
- Предизвикателство: Имплементация на сортиране чрез сливане
- Сливане с линейно време
- Предизвикателство: Имплементация на сливане
- Анализ на сортиране чрез сливане
© 2023 Khan AcademyУсловия за ползванеДекларация за поверителностПолитика за Бисквитки
Анализ на сортиране чрез сливане
Ако ни е дадено, че функцията време при сливането на елемента, как ще покажем, че ? Ще започнем, като си спомним за трите части на "разделяй и владей" и как да обясним техните времена за изпълнение. Ще предположим, че сортираме общо елемента за целия масив.
merge
се изпълнява за mergeSort
се изпълнява за време - Стъпката "разделяй" отнема едно и също време без значение от размера на подмасива. В крайна сметка тази стъпка просто изчислява средната точка
на индексите и . Припомни си, че в нотацията big-Θ указваме константно време с . - Стъпката "владей", в която двата подмасива от по
елемента се сортират рекурентно, отнема някакво време, но ние ще го вземем предвид, когато разглеждаме подзадачите. - Стъпката "комбинирай" слива общо
елемента и отнема време .
Ако помислим за двете стъпките на разделяне и комбиниране, времето за изпълнение за разделянето е от по-нисък порядък в сравнение с времето за изпълнение на стъпката на комбиниране. Затова нека мислим за времето, което двете стъпките на разделяне и комбиниране отнемат заедно, като . За да станат нещата още по-конкретни, да кажем, че общо стъпките на разделяне и комбиниране отнемат време за някаква константа .
За да оставим нещата разумно прости, да приемем, че, ако , то винаги е четно, така че, когато трябва да мислим за , то винаги е цяло число. (Дори и в случая да е нечетно, това няма да промени резултата по отношение на нотацията Θ.) Сега можем да помислим за времето за изпълнение на като сумата от два пъти времето за изпълнение на елемента (за стъпката "владей") плюс (за стъпките "разделяй" и "комбинирай" – в действителност само за сливането).
mergeSort
на подмасив с mergeSort
на подмасив от Сега трябва да открием времето за изпълнение на двете рекурентни извиквания за елемента. Всяко от тези две рекурентни извиквания отнема два пъти времето за изпълнение на елемента (защото трябва да разделим ) плюс за сливането. Имаме две подзадачи с размер и всяка отнема време за сливане и така общото време, което трябва за сливането на подзадачи с размер , е .
mergeSort
на подмасив от Да нанесем времето за сливане в "дърво":
Компютърните специалисти рисуват дърветата от горе надолу – обратно на начина, по който растат истинските дървета. Едно дърво е граф без цикли (пътища, които започват и завършват на едно и също място). Според конвенцията възлите на дървото се наричат върхове. Коренът е на върха. Тук коренът е отбелязан с размер на подмасива от първоначалния масив с елемента. Под корена има два наследяващи върха, всеки от които е отбелязан с , за да покаже размерите на подмасивите за двете подзадачи с размер .
Всяка от подзадачите с размер рекурентно сортира два подмасива с размер или . Тъй като има две подзадачи с размер , има четири подзадачи с размер . Всяка от тези четири подзадачи слива общо елемента и така времето за сливане на четирите подзадачи е . Сумираме четирите подзадачи и виждаме, че общото време за сливане на всички подзадачи с размер е :
Какво според теб ще се случи с подзадачите с размер ? Ще има осем такива подзадачи, а времето за сливане на всяка ще е за общо време за сливане :
Тъй като всички подзадачи стават по-малки, броят на подзадачите се удвоява на всяко "ниво" на рекурсията, но времето за сливане се разделя на две. Удвояването и разделянето се анулират и така общото време за сливане е за всяко ниво на рекурсията. Накрая стигаме до подзадачи с размер 1: основният случай. Трябва ни време , за да сортираме подмасив с размер 1, защото трябва да проверим дали , а тази проверка отнема време. Колко подмасива с размер 1 има? Тъй като започваме с елемента, трябва да има подмасива. Тъй като всеки основен случай отнема време , да кажем, че общо основните случаи отнемат време :
Сега знаем колко време отнема сливането на подзадачите от всеки размер. Общото време за изпълнение на нива, общото време за сливане е . А колко е ? Започваме с подзадачи с размер и ги разделяме на половина, докато стигнем до подзадачи с размер 1. Видяхме тази характеристика, когато анализирахме двоичното търсене и отговорът е . Например, ако , то и е достатъчно сигурно, че дървото има четири нива: . Тогава общото време за . Когато използваме нотацията Θ, за да опишем това време за изпълнение, можем да отхвърлим членовете от нисък порядък ( ) и константния коефициент ( ), което ни дава време за изпълние , както очаквахме.
mergeSort
е сумата на времето за сливане на всички нива. Ако в дървото има mergeSort
е Трябва да отбележим още нещо за сортирането чрез сливане. По време на сливането се прави копие на целия сортиран масив с една половина
lowHalf
и друга highHalf
. Тъй като в някакъв момент се копират повече от константните елементи, казваме, че сортирането чрез сливане не работи на място. За разлика от него сортирането чрез пряка селекция и чрез вмъкване работят на място, тъй като никога не правят копие на повече от постоянният брой елементи на масива, в който и да било момент. Добре е да се отчита дали алгоритъмът работи на място, защото има системи, в които се предпочита работата на място, и в тогава се предпочитат такива алгоритми.Това съдържание е резултат от съвместната дейност на преподавателите по Компютърни науки в Дартмут Thomas Cormen и Devin Balkcom, както и на екипа по компютърни науки на Кан Академия. Съдържанието е лицензирано CC-BY-NC-SA.
Искаш ли да се присъединиш към разговора?
Все още няма публикации.