Добавлен: 15.11.2018
Просмотров: 5622
Скачиваний: 36
3 1 2 6 5 4
а b с
3 1 2 6 5 4
аb с
3 1 2 4 5 6
аbс
Значения переменных After и Before совпадают. Это означает завершение выполнения действий уровня 1, в результате чего исходный массив будет разбит на две подпоследовательности элементов: левую и правую. В левой подпоследовательности находятся элементы, значения которых меньше значения контрольного элемента, а в правой – элементы, значения которых больше или равны значению контрольного элемента.
Вызов процедуры Quick_Sort(A, First, After-1) приведет к переходу на уровень 2. Так как фактические параметры процедуры First = 1, а After-1 = =4 - 1 = 3, то процедурой Quick_Sort будет обрабатываться последовательность, состоящая из 3 элементов и находящаяся слева от контрольного элемента, т.е. 3 1 2. Поэтому этот уровень обработки массива обозначим как 2.Л, , где символ Л означает обработку левой подпоследовательности. Ниже приводятся результаты ее обработки процедурой Quick_Sort.
Уровень 2.Л. Последовательность 3 1 2
a bc
3 1 2
a b с
1 3 2
a b c
1 3 2
ab c
1 2 3
abc
Совпадение значений After и Before означает завершение уровня 2.Л и переход на уровень 3.Л, так как опять происходит вызов процедуры Quick_Sort(A, First, After-1) обработки левой подпоследовательности элементов. Обрабатываемая подпоследовательность состоит только из 1 элемента, так как First = 1, а Last = After – 1 = 2 – 1 = 1.
Уровень 3.Л. Так как условие First < Last не выполняется, то никаких действий в процедуре Quick_Sort(A, First, After-1) не происходит и управление передается оператору вызова процедуры Quick_Sort(A, After+1, Last). Программа переходит на уровень 3.П. На этом уровне обрабатывается подпоследовательность, стоящая справа от контрольного элемента, полученного на уровне 2. В рассматриваемом примере эта подпоследовательность состоит только из одного элемента равного 3.
Уровень 3.П. При вызове процедуры Quick_Sort(A, After+1, Last) формальный параметр First получит значение First = After + 1 = 1 + 1 =2, а формальный параметр - Last = 1. Условие First < Last не выполняется, и программа переходит на уровень 2.П, где обрабатывается подпоследовательность, стоящая справа от контрольного элемента, равного 4.
Уровень 2.П. Последовательность 5 6
a bc
5 6
abс
Уровень 3.Л. Процедурой Quick_Sort(A, First, After-1) обрабатывается последовательность, состоящая из одного элемента, равного 5, параметр First = Last, поэтому происходит переход на уровень 3.П.
Уровень 3.П. Так как обрабатываемая подпоследовательность на этом уровне состоит из одного элемента, то происходит возврат на уровень 2.
Обработка подпоследоватедьностей, стоящих слева и справа от контрольного элемента, полученного на уровне 1 и равного 4, закончена. Программа возвращается на уровень 1, где происходит выход из процедуры Quick_Sort в основную программу. Действие программы завершается выводом результата:
Отсортированный массив
1 2 3 4 5 6.
Контрольные вопросы
-
Зачем нужно сортировать массив данных?
-
Что такое сортировка данных?
-
Какие группы сортировок существуют? Чем они отличаются друг от друга?
-
Какие способы прямых сортировок Вы знаете?
-
Как выглядит алгоритм “пузырьковой” сортировки?
-
Как выглядит алгоритм сортировки выбором?
-
Как выглядит алгоритм сортировки вставкой?
8. В чем суть алгоритма сортировки бинарными вставками?
Задачи
-
Дан одномерный массив Х, состоящий из N элементов, N – заданное натуральное число. Упорядочить элементы массива по неубыванию методом “пузырька”.
-
Дан одномерный массив Х, состоящий из N элементов, N – заданное натуральное число. Упорядочить элементы массива по невозрастанию методом вставки.
3. Дан одномерный массив А, состоящий из N элементов, N – заданное натуральное число. Упорядочить элементы массива по неубыванию методом выбора.
4. Даны целые x1, ..., xп. Получить в порядке возрастания все различные числа, входящие в x1, ..., xп. Воспользоваться алгоритмом сортировки бинарными вставками. В процессе сортировки следует отбрасывать элементы, уже встречавшиеся раньше. Если в результате поиска места xi в упорядоченной совокупности x1, ..., xk (k < i) обнаружится, что среди x1, ..., xk есть элемент, равный xi, то следует перейти к рассмотрению xi+1 без изменения x1, ..., xk .
5. Даны действительные попарно различные a1, ,.., аn. Получить попарно различные целые j1, ..., jn, такие, что 1≤ jk ≤ n (k=1, ..., n) и
6. Даны целые a1, ..., an. Найти наибольшее значение, содержащееся в последовательности чисел a1, ..., an после выбрасывания из нее:
а) одного из членов со значением mах (a1, ..., an);
б) всех членов со значением mах (a1, ..., an).
7. Даны натуральные п, a1, ..., an (n > 4). Числа a1, ..., an — это измеренные в сотых долях секунды результаты п спортсменов в беге на 100 м. Составить команду из четырех лучших бегунов для участия в эстафете 4 100, т. е. указать одну из четверок натуральных чисел i, j, k, I такую, что 1 ≤i < j < k < l≤ n и сумма ai + aj +ak + al имеет наименьшее значение.
8. Задан одномерный массив строк из N элементов. Отсортировать его элементы по алфавиту.
9. Радиостанция провела опрос 120 слушателей. Каждому был задан вопрос: “За кого из 13 политиков Вы намерены голосовать на предстоящих выборах?“ Составить программу получения 5 наиболее часто встречающихся ответов и их долей (в %), результат вывести в виде таблицы.
10. Составить программу для обработки результатов кросса на 500 м для женщин. В кроссе участвует не более 100 студенток. В протоколе указывается фамилия, шифр группы, результат. Получить итоговую таблицу результатов спортсменов в порядке занятых ими мест. Определить количество участниц, выполнивших заданный норматив.
11. Лыжные гонки проводятся отдельно для двух групп участников (в каждой группе не более 15 человек). Протокол соревнований каждой группы включает в себя фамилии участников и результат. Объединить результаты в обеих группах, упорядочить фамилии спортсменов в порядке занятых ими мест и вывести в виде таблицы с заголовком.
12. На конкурсе песни каждый зритель должен назвать лучшую по его мнению песню и ее исполнителя. Обработать результаты опроса, упорядочив их по количеству голосов и вывести в виде таблицы информацию о первых десяти песнях, возглавляющих список (песня, исполнитель, количество голосов).
13. Результаты соревнований по прыжкам в длину определяются по сумме двух попыток. В протоколе для каждого участника указываются фамилия, общество, результаты первой и второй попыток. Вывести протокол в виде таблицы с заголовком с фамилиями участников соревнований в порядке занятых мест.
5.2 Поиск
При подготовке таблиц статистических сводок, справочных изданий, словарей, как правило, производят упорядочивание данных. Это делает работу с таблицей, справочником и тому подобными более удобной. Например, выигравшие номера упорядочены в лотерейных таблицах по возрастанию. Упорядоченность облегчает проверку билета: если бы номера не были упорядочены, то проверка могла бы потребовать сравнения номера билета со всеми номерами, содержащимися в таблице. Точно так же словарный порядок облегчает поиск слова в словаре или справочнике.
Поиск сведений в разнообразных таблицах и сводках может быть возложен на компьютер. Мы будем заниматься алгоритмом быстрого поиска элемента в упорядоченной совокупности а1, ..., аn. При этом будем считать, что a1, ..., an - целочисленный массив, b - некоторое целое число. Работая со словарем, мы имеем дело не с целыми числами, а со словами, но это не играет принципиальной роли: меняется только техника каждого сравнения, а не число сравнений.
Пусть a1<...<an . Рассмотрим задачу: выяснить, входит ли данное число b в массив a1, ..., аn, и если входит, то каково значение р, для которого аp=b? Эту задачу мы назовем задачей поиска элемента. Тривиальный алгоритм решения этой задачи основывается на последовательных сравнениях b с элементами a1, ..., аn: сравнить b с a1, если они равны, то р=1, иначе сравнить b с a2 и т. д. Среднее число требуемых здесь сравнений можно считать равным n/2. Известен алгоритм, который требует гораздо меньших затрат.
Предположим, что в массиве a1, ..., аn имеется элемент, равный b, т. е. существует такое р, что аp = b. По результату любого сравнения аs < b (1 ≤ s ≤ n) мы сразу определяем, лежит ли р в диапазоне от 1 до s или же в диапазоне от s + l до n: второе будет иметь место, если неравенство аs < b справедливо, а первое—если несправедливо. Если само s находится примерно посередине между 1 и n, то сравнение аs < b сужает диапазон поиска примерно вдвое. Этот прием можно использовать многократно. Получается алгоритм, называемый алгоритмом деления пополам. В соответствии с этим алгоритмом надо взять первоначально 1 и п в качестве границ поиска индекса элемента; далее, до тех пор, пока границы не совпадут, шаг за шагом сдвигать их следующим образом: сравнить b с as, где s—целая часть среднего арифметического границ; если as < b, то заменить прежнюю нижнюю границу на s + 1, оставив верхнюю границу без изменения, иначе оставить без изменения нижнюю границу, а верхнюю заменить на s. Поиск закончится, когда границы совпадут.
Сказанное можно записать в виде последовательности операторов Паскаля (р и q обозначают упомянутые верхнюю и нижнюю границы; когда р и q совпадут, выполнение алгоритма закончится, и р дает результат выполнения);
р:=1; q:= n;
while р < q do
begin
s: =(p+q) div 2;
if a[s] < b then p:= s+1
else q:= s
end;
Вообще идея деления пополам (сведение задачи к примерно вдвое более простой в количественном отношении) оказывается весьма плодотворной для построения многих алгоритмов. В научной литературе деление пополам иногда именуется греческим термином «дихотомия» или латинским «бисекция», а для обозначения сущности самой идеи иногда используются слова «разделяй и властвуй».
Заметим сразу следующее. Мы исходим из предположения, что среди элементов a1, ..., аn имеется такой, который равен b. Если заранее неизвестно, имеется или нет такой элемент, то, получив р, надо дополнительно проверить, действительно ли аp=b. И если обнаружится, что равенство несправедливо, то из этого будет следовать, что среди a1, ..., аn нет элемента, равного b.
Продемонстрируем применение этого алгоритма на конкретном примере. Пусть a1, ..., а10 соответственно равны 2, 3, 5, 7, 11, 13, 17, 19, 23, 29. Тогда для b = 19 поиск будет разворачиваться следующим образом. В начале границы поиска равны 1 и 10. Имеем [(1 + 10) / 2] = 5, неравенство а5 < b, т.е. 11 < 19, справедливо, поэтому переходим к границам 6, 10. Имеем [(6 +10) / 2] = 8, неравенство a8 < b, т.е. 19 < 19, несправедливо, поэтому переходим к границам 6, 8. Имеем [(6+8)/2] = 7, неравенство a7 < b, т. е. 17 < 19, справедливо, поэтому переходим к границам 8, 8. Эти границы совпадают; следовательно, если в массиве вообще есть элемент со значением b, то это a8. В данном случае равенство b = a8 справедливо, так как 19 = 19.
Нетрудно убедиться, что если бы мы взяли в качестве b не 19, а 18, то до самого последнего момента применение алгоритма разворачивалось бы точно так же, но в самом конце дополнительная проверка равенства a8 = b дала бы отрицательный результат, что явилось бы свидетельством того, что в массиве a1, ..., аn нет элемента со значением 18.
Алгоритм поиска элемента делением пополам обладает высоким быстродействием. Если п=2m, то число сравнений b с элементами a1, ..., аn в процессе применения этого алгоритма не превзойдет m, а если п не равно 2m ни для какого целого т, то в качестве границы для числа сравнений можно взять наименьшее m такое, что n < 2m (без учета дополнительного сравнения ар=b, необходимого в том случае, когда заранее неизвестно, имеется или нет среди a1, ..., аn элемент, равный b).
Например, если n = 10, то число сравнений не превосходит 4, так как 10 < 24, для n = 32 это число не превосходит 5, так как 32 = 25, для n = 1000 это число не превосходит 10, так как 1000 < 210 и т. д.
Теперь мы приведем пример программы, использующей написанную выше последовательность операторов, т.е. алгоритм деления пополам.
Пусть таблица выигрышей лотереи представлена в виде двух массивов a1, ..., аn и с1, ..., сn (n - некоторая константа) так, что натуральные a1, ..., аn — это выигравшие номера (а1 < ...< аn), a c1, ..., cп - действительные положительные числа, означающие выигрыши в рублях, выпавшие соответственно на номера a1, ..., аn. Требуется найти выигрыши, выпавшие на ряд номеров (если номера нет в таблице, то выигрыш считается равным нулю). Схема программы:
program Loto;
описания;
begin
ввод массивов а и с;
1: write(‘ номер='); read(b);
найти р - предполагаемое место b в массиве а;
if a[p]=b then f:= c[p] else f:=0;
writeln(' выигрыш =',f); goto 1
end.
Мы легко можем детализировать эту схему и получить настоящую программу. Условимся, что значения элементов массивов а и с заданы в следующей последовательности: a1, с1, а2, с2,... an, cn, где n—константа, значением которой будем считать 20:
program Loto;
const n =20;
type u=array[1 .. n] of integer;
v=array[1.. n] of real;
var a:u;
c:v;
i, p, q, s, b:integer;
f:real;
begin
for i:=1 to n do read(a[i], c[i]);
write('HOMЕР='); read(b);
p:=1; q:=n;
while p < q do
begin
s:=(p+ q) div 2;
if a[s] < b then p:= s+1
else q:=s
end;
if а[р]=b then f:=c[p]
else f:= 0;
writeln('выигрыш=' ,f);
end.
Идея деления пополам («разделяй и властвуй») может быть положена в основу алгоритма решения еще одной задачи, похожей на задачу поиска элемента. Пусть по-прежнему a1 < a2 < ... < аn, и пусть b—некоторое число. Для числа b имеется n + 1 возможность: b ≤ a1, a1 < b ≤ a2, a2 < b ≤ a3, ..., an-1 < b ≤ an, an < b.
Требуется определить, какая из возможностей имеет место. Ответом должно быть одно из чисел 1, 2, ..., n, n+1 (порядковый номер возможности).
По результату любого сравнения as < b, 1 ≤ s ≤ n мы сразу определяем, лежит ли ответ в диапазоне от 1 до s или же в диапазоне от s+1 до n+1. Если само s находится примерно по середине между 1 и n+1, то сравнение аs < b сужает диапазон поиска примерно вдвое. Это приводит к следующему алгоритму:
р:=1; q:=n+1;
while p < q do
begin
s: =(p+q) div 2;
if a[s] < b then p:=s+1
else q:=s
end;
Единственное отличие последнего алгоритма от алгоритма поиска элемента состоит в начальном присваивании q:=n+1 (вместо q:=n). Этот алгоритм удобен, например, когда надо вставить в таблицу новый элемент, не нанося при этом ущерба упорядоченности таблицы. Этот алгоритм называется алгоритмом поиска места элемента (до него мы рассматривали алгоритм поиска элемента: названия похожи, но не совпадают).
Контрольные вопросы
-
Какие методы поиска данных в массиве Вы знаете?
-
В чем состоит алгоритм прямого перебора?
-
Как выглядит алгоритм бинарного поиска?
-
Как должен быть преобразован массив для организации бинарного поиска?
-
Как определяется быстродействие алгоритма бинарного поиска?
Задачи
1. Изменить программу Loto: как только в качестве номера (т.е. значения переменной b) с клавиатуры указывается отрицательное число, выполнение программы должно заканчиваться.
2. Изменить программу Loto: не нужно выводить все выигрыши по отдельности, потребуется вывести суммарный выигрыш, выпавший на все указанные номера. В качестве сигнала об окончании последовательности номеров используется любое отрицательное число (см. предыдущую задачу).
3. Изменить программу Loto, предполагая, что номера в таблице заданы в порядке убывания: а1 > а2 >...> аn.
4. Даны натуральные a1, ..., a50, т, b1, .... bm, (a1 > а2 > ... > a50). Подсчитать количество тех bi , 1 ≤ i ≤ т, для которых нет равных среди а1, ..., a50.