Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

информатика.Методы сортировок

.pdf
Скачиваний:
10
Добавлен:
04.06.2015
Размер:
2.25 Mб
Скачать

И. В. Беляева К. с. Беляев

МЕТОДЫ СОРТИРОВОК

И их РЕАЛИЗАЦИИ

Ульяновск

2006

Федеральное агентство по образованию Государственное образовательное учреждение высшего профессионального образования

Ульяновский государственный техниический университет

МЕТОДЫ СОРТИРОВОК

И ИХ РЕАЛИЗАЦИИ

методические указания к выполнению лабораторных работ по программированию для студентов направлений 23010062 «Информатика и вычислительная техника и специальности 230 1о 165«Вычислительные

машины, комплексы, системы и сети»

Составители: и. В. Беляева К. С. Беляев

Ульяновск 2006

УДК 681.3(076)

ББК 32.973я7 М54

Рецензент кандидаттехническихнаук, профессор, декан ФИСТ В. В. Шишкин

Одобрено секцией методическихпособий научно-методического

совета университета

Методы сортировоки их реализации: методическиеуказания к М54 выполнениюлабораторныхработ / сост. и. В. Беляева, К. с. Беляев.­

Ульяновск: УлГТУ, 2006. - 48 с.

Рассмотрены алгоритмы сортировок и их реализация на языке С++. В данном методическом указании освещены следующие методы сортировок: методом выбора, метода пузырька, методом вставок, методом слияния и быстрая сортировка. Подробно рассмотрены вопросы оценки эффективности алгоритмов с использованием нотации О ­ большое.

В методическое указание включены задания для лабораторной работы «Методы

сортировок».

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

Работа подготовлена на кафедре ВТ.

УДК 681.3(076)

ББК 32.973я7

© и. В. Беляева, К. с. Беляев, составление, 2006 © Оформление. УлГТУ, 2006

ОГЛАВЛЕНИЕ

ВВЕдЕНИЕ

4

ИЗМЕРЕНИЕ ЭФФЕКТИВНОСТИ АЛГОРИТМОВ

5

БЫСТРОДЕЙСТВИЕ АЛГОРИТМОВ

6

СТЕПЕНЬ РОСТА ВРЕМЕННЫХ зАТРАТ

7

ОЦЕНКА ПОРЯДКА ВЕЛИЧИНЫ И ОБОЗНАЧЕНИЕ О-БОЛьшОЕ

8

ЭФФЕКТИВНОСТЬ АЛГОРИТМОВ ПОИСКА

14

АЛГОРИТМЫ СОРТИРОВКИ И ИХ ЭФФЕКТИВНОСТЬ

15

СОРТИРОВКА МЕТОДОМ ПУЗЫРЬКА

19

СОРТИРОВКА МЕТОДОМ ВСТАВОК

22

СОРТИРОВКА СЛИЯНИЕМ

24

БЫСТРАЯ СОР'ТИРОВКА

30

СРАВНЕНИЕ АЛГОРИТМОВ СОРТИРОВКИ

44

ЛАБОРАТОРНАЯ РАБОТА «МЕТОДЫ СОРТироВоК»

44

ЦЕЛЬ РАБОТы

44

ОБЩЕЕ ЗАДАНJ!IЕ

44

ВАРИАНТЫ

45

БИБЛИОГРАФИЧЕСКИЙ сПИСОК

48

3

Введение

Развитие компьютерной техники, позволившее хранить и обрабатывать огромные объемы информации, вызвало необходимость в методах и средствах, обеспечивающих ее сортировку. Критерием выбора того или иного метода сортировки является его быстродействие. Быстродействие метода зависит от самого алгоритма лежащего в его основе, так 1--1 от его реализации. Причем зачастую складывается ситуация, что алгоритм, прекрасно показавший себя при

сортировке данных одного размера, проигрывает другому алгоритму при

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

Цель данных методических указаний - изучение алгоритмов сортировок и оценка их эффективности. Были рассмотрены наиболее популярные методы сортировок: методом выбора, методом вставок, методом пузырька, методом слияния и быстрая сортировка. Авторы старались простым языком донести

сущность алгоритмов и описать их реализацию на языке программирования

высоко уровня. В качестве языка реализации был выбран язык С++ ,

используемые в нем конструкции, позволили создать простые и элегантные

реализации алгоритмов. В пособии рассматриваются оценка алгоритмов с использованием нотации О-большое.

Авторы надеются, что данные методические указания помогут студентам

снаибольшей эффективностью освоить столь важную тему, как методы

сортировок и их реализация.

4

Измерение эффективности алгоритмов

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

еще.

Допустим, два алгоритма решают одну и ту же задачу, например осуществляют поиск данных. Как их сравнить между собой и решить, какой из них лучше? Выясним какакие же факторы, влияют на стоимость компьютерной программы. Некоторые из этих факторов касаются стоимости работы, затраченной на разработку, сопровождение и использование программы. Другие факторы определяют стоимость ее выполнения, т.е. эффективность, выраженную объемом компьютерного времени, необходимого

для выполнения программы.

Анализ алгоритмов (analysis of algorithms) - это область компьютерных наук, изучающая способы сравнения эффективности разных методов решения задач. Обратите внимание, что в этом определении использован термин "метод решения задачи", а не "программа". Следует подчеркнуть., что анализ алгоритмов, как правило, исследует существенные различия эффективности, которые обусловлены собственно методами решения задач, а не остроумными программистскими трюками. Изощренные приемы кодирования, позволяющие снизить стоимость вычислений, чаще всего снижают читабельность программы, тем самым повышая затраты на ее сопровождение и модификацию. Сравнение алгоритмов должно быть сосредоточено на их существенных различиях, поскольку именно их эффективность является основным фактором, определяющим общую стоимость решения. Если два алгоритма выполняются

несколько часов, а разница между временем их выполнения составляет

несколько секунд, их эффективность одинакова.

При анализе эффективности одинаково важны как время выполнения алгоритма, так и занимаемая им память. Для анализа этих факторов

используются аналогичные методы.

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

1. Как

запрограммированы

алгоритмы? Допустим, алгоритм А1

выполняется быстрее,

чем алгоритм А2• Это может быть связано с

тем,

что программа,

реализующая алгоритм А1 просто лучше

написана. Следовательно, сравнивая время выполнения программ,

вы на самом деле сравниваете реализации алгоритмов, а не сами

алгоритмы. Реализации алгоритмов сравнивать бессмысленно,

5

поскольку они очень сильно зависят от стиля программирования и

не позволяют определить, какой из алгоритмов эффективнее.

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

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

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

показано в следующем разделе, эти методы начинаются с подсчета основных

операций, выполняемых при решении задачи.

Бы тродействиеe алгоритмов

Быстродействие алгоритма связано с количеством выполняемых операций, поэтому оценить его эффективность можно путем их простого подсчета. Рассмотрим несколько примеров.

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

N ode *сцг == head;

<- 1 присваивание

while (cur !== NULL

<- п+1 сравнений

{

 

cout « cur->itetn «

endl · <- n

cur == cur->next;

<- n

операций записи

присваиваний

} // Конец цикла while

6

В предположении, что связанный список состоит из п узлов, эти операторы выполняют n+ 1 присваивание, n+ 1 сравнение и п операций записи. Если каждое присваивание, сравнение и операция записи выполняется за а, Ь и с единиц времени, то на выполнение данного фрагмента программы уйдет (n+1) *(а+с)+n *и> единиц времени. Итак, можно интуитивно догадаться, что вывод на экран содержимого 100 узлов связанного списка будет выполняться дольше, чем вывод содержимого 1О узлов.

Вложенные циклы. Рассмотрим алгоритм, содержащий вложенные

циклы.

[о« (! == 1 до n)

[о» (j == 1 до ')

[о» (k == 1 до 5)

Задача Т

Если задача Т решается за t единиц времени, то на выполнение наиболее глубоко вложенного цикла по переменной k уйдет 5 * t единиц времени. Цикл по переменной j затратит 5 * t * i единиц времени, а внешний цикл по переменной i будет выполняться за

L(5 * t * i) == 5 * t * (1 + 2 +... + n) == 5 * t * п * (n +1)/2

единиц времени.

Степень роста временных затрат

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

измерения размера задачи зависит от конкретного приложения - количества

узлов связанного списка, размера массива или количества элементов стека.

Итак, мы приходим к следующим выводам.

Для решения задачи, имеющей размер п, алгоритм А

затрачивает n2/ i единиц времени.

Для решения задачи, имеющей размер п, алгоритм В затрачивает 5*п единиц времени.

Единицы времени, используемые при оценке эффективности этих алгоритмов, должны быть одинаковыми. Например, утверждение может

выглядеть так.

Для решения задачи, имеющей размер n, алгоритм А затрачивает

nС'/5секунд.

Выше мы уже перечислили трудности, возникающие на этом пути.

На каком компьютере алгоритм будет выполнен за n2/5 секунд? Какая

реализация этого алгоритма выполняется за п:) /5 секунд? При каких

данных алгоритм выполнится за n2/5 секунд?

7

Что конкретно нужно знать о быстродействии алгоритма? Важнее всего знать, насколько быстро возрастает время его выполнения с увеличением размера задачи. Степень роста временных затрат (growth rate) выражаетсяследующимивысказываниями.

Время выполнения алгоритма А прямо пропорционально п2.

Время выполнения алгоритма В прямо пропорционально n

По этим утверждениям нельзя определить, сколько именно времени выполняется алгоритм А или В. Главное, что при решении больших задач алгоритм В работает намного быстрее. Иными словами, объем времени, затрачиваемый алгоритмом В, выраженный функцией, зависящей от размера задачи, растет медленнее, чем время выполнения алгоритма А, поскольку линейная функция растет медленнее квадратичной. Даже если В

действительно затрачивает 5 * n секунд, в то время как алгоритм А

выполняется за n2/5 секунд, в целом алгоритм В выполняется значительно

быстрее алгоритма А. Эта ситуация проиллюстрирована на рис. 1. Таким

образом, выражение Время выполнения алгоритма А прямо пропорционально

n2 точно характеризует эффективность алгоритма и не зависит от конкретных

компьютеров и реализаций.

Алгоритм А выполняется за п2/5 секунд

Алгоритм В выполняется за 5*п секунд

n 25

РИСУНОК 1. Время выполиения алгоритмов как функция, зависящая от размера задачи n

Оценка порядка величины и обозначение О-большое

Допустим, выполняется следующее утверждение.

Время выполнения алгоритма А прямо пропорционально функции f(n}. В таких случаях говорят, что алгоритм А имеет порядок f(n} (order f(n)). Этот факт обозначается как О(f(n)). Функция f(n) называется сложностью алгоритма (growth-rate function). Поскольку в обозначении используется прописная буква О (первая буква слова опаее (порядок)), оно называется обозначением О-большое (Big-O notation).

8

Если время решения задачи прямо пропорционально ее размеру п, то

сложность задачи равна О(n), т.е. имеет порядок n. Если время решения

задачи прямо пропорционально квадрату ее размера, Т.е. n2, то сложность задачи равна о(n2) и т.д.

ОСНОВНЬIE ПОНЯТИЯ

Определение порядка алгоритма

Алгоритм А имеет порядокДн). Этот факт обозначается как O(f(o)), если существуют константы k и по такие, что при решении задачи, имеющей размер n ?.nо, алгоритм А выполняется не более чем за k* f(n} единиц времени.

Условие п > по формализует интуитивное понятие большой задачи. Как правило, этому определению удовлетворяет большинство значений переменных k и n. Проиллюстрируем определение несколькими примерами.

Допустим, что при решении задачи, имеющей размер n, алгоритм

выполняется за п2-3*п+1О секунд. Если существуют такие константы k и ПО,

что

k * n 2 > n 2 - 3*n+ 1О для всех п ~ по,

то алгоритм имеет порядок п2 • Фактически если константа k равна 3,

а число по равно 2, то

3 * n2 > n2 - 3 *n + 1О для всех п> 2,

как показано на рис.2. Таким образом, при п ~ по дЛЯ выполнения алгоритма потребуется не более k * п:') единиц времени.

Ранее мы показали, что для вывода на экран первых п элементов

связанного списка потребуется

(n+ 1) *(a+c)+n*w единиц

времени.

Поскольку неравенство 2*n 2: n+ 1

выполняется для всех n 2:

1, имеет

место неравенство

 

 

(2*а+2*с+ w)*n 2: (n+ l)*(a+c)+n* w для всех п 2: 1.

Следовательно, сложность задачи имеет порядок О(п). Здесь константа k равна числу 2 *а+2 *c+w, а константа по равна 1.

Требование n 2: по, в определении величины O(f(n)) означает, что оценка времени будет корректной лишь для достаточно больших задач. Иными словами, если задача имеет относительно небольшие размеры, то оценка времени ее решения будет слишком заниженной. Например, функция log n равна О, если число n равно 1. Итак, из того, что число k * log 1 равно О при любых значениях константы k, следует неправильная оценка времени. Для выполнения любого алгоритма требуется не нулевое

9