Delphi_part2
.pdf
1sortInsert ( mas, count )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
Индекс начала |
||||||
|
|
|
|
|
|
|
|
|
|
i := 2 |
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
неупорядоченной части |
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
3 |
|
|
|
|
i <= count |
|
|
|
12 |
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
нет |
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
да |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
4 |
mas[i] < mas[i-1] |
|
|
|
нет |
11 |
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
да |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
Запоминаем элемент, который |
|
|||||||
|
|
|
|
|
tmp := mas[i] |
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
нужно разместить слева |
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Индекс освободившегося места |
|||||||
|
|
|
|
|
|
|
|
|
|
j := i |
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Сдвигаем вправо на |
||||
|
|
|
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
mas[j] := mas[j-1] |
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
освободившееся место |
||||||||||||||||
|
|
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|||||
нет |
|
|
|
|
|
|
|
|
j := j - 1 |
|
|
|
Свободное место уходит влево |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
(j=1) or (mas[j-1]<=buf) |
|
|
|
|
|
|
|
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
да |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
10 |
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
a[j] := buf |
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
i := i + 1 |
|
|
4 |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
конец |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
12 |
3 |
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
Рисунок 8.15 - Алгоритм сортировки по возрастанию методом вставки
Внутренний цикл обеспечивает последовательные сдвиги упорядоченных элементов вправо, начиная с последнего, до тех пор, пока не будет найдено место для первого элемента из неупорядоченной области.
Возможность вставки элемента определяется одним из двух условий.
–mas[j-1] <= buf < mas[j] и 1 < j < i, т.е. найдено место внутри упорядоченной последовательности.
–j=1 , т.е. tmp является самым малым элементом и вставляется на первое место в упорядоченной части массива.
После завершения цикла сдвигов элемент массива из переменной tmp переносится на найденное место в упорядоченной последовательности.
8.1.3.1 Пример сортировки массива по возрастанию методом вставки
Результаты последовательных шагов сортировки представлены на рисунках 8.16 - 8.20.
31
Первоначальная разбивка массива: |
|
|
|
||
A[1] |
A[2] |
A[3] |
|
A[4] |
A[5] |
6 |
4 |
10 |
|
5 |
7 |
упорядоченная часть |
|
неупорядоченная часть |
|||
(A[1]) |
|
(A[2], A[3], A[4], A[5]) |
|
||
Рисунок 8.16 – Исходное разбиение массива при сортировке методом вставки
|
A[1] |
|
|
A[2] |
A[3] |
A[4] |
A[5] |
|||
|
|
|
||||||||
|
6 |
|
4 |
|
|
|
10 |
5 |
7 |
|
|
|
|
|
A[2] < A[1], |
ему нужно найти место в левой части. |
|||||
|
|
|
|
|||||||
Переносим A[2] в буфер |
|
|
|
|||||||
|
A[1] |
|
|
A[2] |
A[3] |
A[4] |
A[5] |
|||
|
|
|
||||||||
|
6 |
|
|
|
|
|
|
10 |
5 |
7 |
|
|
|
Buf |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|||
|
|
|
|
4 |
|
|
|
|
|
|
Сдвигаем A[1] на место A[2] |
|
|
|
|||||||
|
A[1] |
|
|
A[2] |
A[3] |
A[4] |
A[5] |
|||
|
|
|
||||||||
|
|
|
6 |
|
|
|
10 |
5 |
7 |
|
|
|
|
|
Buf |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
||
|
|
4 |
|
|
|
|
|
|
||
Проверяем, подходит ли освободившееся место для элемента из буфера. Место подходит, поэтому перемещаем из буфера в позицию A[1].
A[1] |
A[2] |
A[3] |
A[4] |
A[5] |
4 |
6 |
10 |
5 |
7 |
|
Buf |
|
|
|
Теперь в левой половине массива уже два упорядоченных элемента.
Рисунок 8.17 – Результаты выполнения первого шага сортировки вставкой
32
|
|
|
|
|
|
|
|
|
|
A[1] |
A[2] |
|
A[3] |
A[4] |
A[5] |
|
|
|
5 |
6 |
|
10 |
4 |
|
7 |
|
|
|
|
|
|
|
|||
|
|
A[3] > |
A[2], никаких перестановок не требуется. |
|
||||
|
|
Граница левой области сдвигается вправо. |
|
|
||||
|
A[1] |
A[2] |
|
A[3] |
A[4] |
A[5] |
|
|
|
6 |
5 |
|
10 |
4 |
|
7 |
|
Рисунок 8.18 – Результаты выполнения второго шага сортировки вставкой
|
A[1] |
A[2] |
A[3] |
|
A[4] |
|
A[5] |
||||
|
|
||||||||||
|
4 |
6 |
|
10 |
|
|
5 |
|
7 |
|
|
|
|
|
|
|
|
|
|
||||
|
|
A[4] < A[3], |
ему нужно найти место в левой части. |
||||||||
Переносим A[4] в буфер |
|
|
|
|
|
|
|
|
|||
|
A[1] |
A[2] |
A[3] |
|
A[4] |
|
A[5] |
||||
|
|
|
|||||||||
|
4 |
6 |
|
10 |
|
|
|
|
7 |
|
|
|
|
|
|
|
|
|
Buf |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
Сдвигаем A[3] на место A[4] |
|
|
5 |
|
|
|
|
||||
|
|
|
|
|
|
|
|
||||
|
A[1] |
A[2] |
A[3] |
|
A[4] |
|
A[5] |
||||
|
|
|
|||||||||
|
4 |
6 |
|
|
|
10 |
|
|
7 |
|
|
|
|
|
|
|
|
|
Buf |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
Проверяем, подходит ли освободившееся |
|
5 |
элемента и буфера. |
||||||||
|
|
место для |
|||||||||
Место не подходит, поэтому перемещаем A[2] в позицию A[3]. |
|||||||||||
|
A[1] |
A[2] |
A[3] |
|
A[4] |
|
A[5] |
||||
|
|
|
|||||||||
|
4 |
|
|
6 |
|
10 |
|
|
7 |
|
|
|
|
|
|
|
|
|
Buf |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
5 |
|
|
|
|
|
Проверяем, подходит ли освободившееся место для элемента и буфера. Место подходит, поэтому перемещаем из буфера в позицию A[2].
A[1] |
A[2] |
A[3] |
A[4] |
A[5] |
4 |
5 |
6 |
10 |
7 |
|
|
|
Buf |
|
Теперь в левой половине массива уже четыре упорядоченных элемента.
Рисунок 8.19 – Результаты выполнения третьего шага сортировки вставкой
33
|
A[1] |
A[2] |
A[3] |
A[4] |
|
|
A[5] |
|||||
|
|
|
||||||||||
|
4 |
5 |
|
6 |
10 |
|
|
7 |
|
|
|
|
|
|
A[5] < A[4], |
ему нужно найти место в |
|
левой части. |
|||||||
|
|
|
||||||||||
Переносим A[5] в буфер |
|
|
|
|
|
|
|
|
|
|||
|
A[1] |
A[2] |
A[3] |
A[4] |
|
|
A[5] |
|||||
|
|
|
||||||||||
|
6 |
|
|
10 |
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Buf |
|
||
|
|
|
|
|
|
|
|
|
|
|||
Сдвигаем A4] на место A[5] |
|
|
|
|
|
7 |
|
|
|
|||
|
|
|
|
|
|
|
|
|
||||
|
A[1] |
A[2] |
A[3] |
A[4] |
|
|
A[5] |
|
||||
|
|
|
|
|||||||||
|
4 |
5 |
|
6 |
|
|
10 |
|
|
|
||
|
|
|
|
|
|
|
|
Buf |
|
|||
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
7 |
|
|
|
||
Проверяем, подходит ли освободившееся место для элемента из буфера. Место подходит, поэтому перемещаем из буфера в позицию A[4].
A[1] |
A[2] |
A[3] |
A[4] |
|
A[5] |
|
|
|
|
||||||
4 |
5 |
6 |
7 |
7 |
|
|
|
Массив упорядочен. |
|
|
|
Buf |
|
||
|
|
|
|
||||
|
|
|
|
|
|
||
|
|
|
|
|
|
||
Рисунок 8.20 – Результаты выполнения четвертого шага сортировки вставкой
8.1.3.2 Процедура сортировки методом вставки
procedure SortInsert(var a:TArray100; count: integer); var i, j, x: integer;
begin
for i := 2 to count do begin
//Сравниваем элементы на границе между
//упорядоченной и неупорядоченной частями массива if a[i] < a[i-1] then
begin
//Порядок нарушен, запоминаем i-й элемент
34
x := a[i];
// Начинаем цикл сдвигов вправо на место i-го элемента j := i; // j – индекс вакантного места
repeat
//сдвигаем вправо a[j]:=a[j-1];
j:=j-1;
//пока слева не появилось меньшее число,
//или дошли до начала массива
until (j = 1) or (a[j-1] <= x);
//'Теперь вставим бывший i-й элемент на новое место с индексом
j
a[j] := x;
end;
end;
end;
8.2 СОРТИРОВКА ПО УСЛОЖНЕННЫМ ПРАВИЛАМ
Выше мы рассмотрели различные методы сортировки массивов, в которых порядок расположения элементов определялся применением простейшей операции сравнения «больше» или «меньше». В результате применения этих операций мы получаем сортировку на возрастание или на убывание.
Однако в некоторых случаях необходимо использовать более сложные критерии сравнения элементов, чем простое сравнение. В этих случаях целесообразно написать функцию сравнения элементов по заданному правилу, которая будет возвращать true, если порядок следования элементов не нарушен и false в противном случае. Эту функцию следует вызывать в тех местах процедуры сортировки, где требуется сравнение элементов.
Например, пусть правило сортировки массива целых чисел сформулировано таким образом: «Вначале четные числа по убыванию, а затем нечетные по возрастанию».
Функция, которая сравнивает элементы в соответствии с таким правилом, приведена ниже.
function GoodDisposition(x1, x2: integer): boolean; begin
if (x1 mod 2) <> (x2 mod 2) then
35
//Случай, когда одно число четное, а другое нечетное //В этом случае четное число считается меньшим result := (x1 mod 2) < (x2 mod 2)
else if x1 mod 2 = 0 then
// Случай, когда оба числа четные result := x1 > x2
else // Случай, когда оба числа нечетные result := x1 < x2;
end;
Теперь с помощью созданной функции можно отсортировать массив в требуемом порядке. Метод сортировки может быть любым. Для примера используем сортировку выборм.
procedure SortChoise (a: TArray100; count: integer); var i, j, x: integer;
begin
for i:= 1 to count-1 do begin
for j := i + 1 to count do
if not GoodDisposition(a[i], a[j]) then begin
x := a[i]; a[i] := a[j]; a[j] := x;
end;
end;
end;
8.3 ОБРАБОТКА УПОРЯДОЧЕННЫХ МАССИВОВ
Упорядоченные массивы чаще всего используются как хранилища некоторой информации. Наиболее часто встречающиеся задачи, связанные с обработкой таких массивов, следующие:
–Добавление элемента в массив, без нарушения порядка
–Объединение двух массивов в один с сохранением порядка
–Поиск позиции элемента в массиве
–Удаление элемента из массива
36
Ниже рассматриваются процедуры и функции, решающие эти задачи.
8.3.1 Вставка элемента в отсортированный массив
Алгоритм вставки элемента в упорядоченный массив уже рассматривался, как часть алгоритма сортировки вставкой. Он заключается в последовательном анализе элементов массива, начиная с последнего и, при необходимости, сдвиге анализируемого элемента вправо на одну позицию, для того, чтобы освободить место для вставляемого элемента. Сдвиги проводятся до тех пор, пока не будет найдено место для вставляемого элемента, соответствующее его значению.
Если все элементы массива больше чем добавляемый элемент, то все элементы массива сдвинутся вправо, а новый будет поставлен на первое место.
Процедура вставки элемента в отсортированный массив приведена ниже.
//Процедура добавления в упорядоченный массив
//x – вставляемый элемент
//а – упорядоченный массив, count – число элементов в
нем
procedure AddToSortArray (x: integer; var a: TArray100; var count: integer); var i: integer;
begin
// В результате вставки число элементов в массиве увеличится на 1 count := count + 1;
i := count - 1; // номер анализируемого элемента while (i >= 1) and (a[i] > x) do
begin
a[i + 1] := a[i]; // сдвигаем вправо i := i - 1;
end;
a[i + 1] := x;
end;
8.3.2Слияние двух отсортированных массивов в один
Вэтом алгоритме текущие элементы исходных массивов сравниваются, и во вновь создаваемый массив переносится меньший элемент. При этом текущая позиция массива, из которого был переписан элемент, перемещается к следующему элементу. Цикл сравнений продолжается до тех пор, пока не исчерпаются элементы одного из массивов. После этого оставшиеся элементы просто дописываются во вновь создаваемый массив.
37
Процедура слияния массивов приведена ниже.
//Процедура слияния двух упорядоченных массивов
//а1, а2 – исходные упорядоченные массивы,
//count1 count2, – число элементов в этих массивах
//а3 – объединенный массив, count3 – число элементов в
нем
procedure MergeSort Array (a1, a2 : TArray100; count1, count2: integer;
var a3: TArray100; var count3:
integer);
var i, j, k: integer; begin
//Число элементов в новом массиве равно сумме исходных
сount3 := count1 + count2;
k:=0; // Текущий индекс в первом массиве i:=0; // Текущий индекс во втором массиве j:=0; // Текущий индекс в третьем массиве while (i <= count1) and (j <= count2) do begin
if a1[i] < a2[j]
then begin // Добавляем элемент из первого массива a3[k]:=a1[i];
i:=i+1;
end
else begin // Добавляем элемент из второго массива a3[k]:=a2[j];
j:=j+1;
end;
k:=k+1;
end;
//Добавляем остаток первого массива, если есть
for i := i to count1 do begin
a3[k]:=a1[i]; k:=k+1;
38
end;
// Добавляем остаток второго массива, если есть for j := j to count 2 do
begin
a3[k] := a2[j]; k : k+1;
end;
end;
8.3.3 Поиск позиции элемента в отсортированном массиве
Для поиска позиции элемента в отсортированном массиве можно использовать метод дихотомии (деления области поиска пополам). В этом методе элемент, который находится в середине области поиска, сравнивается с образцом, который нужно найти. В результате такого сравнения можно определить найден ли отыскиваемый элемент, а если нет, то можно определить, в какой из половин области поиска может находиться искомый элемент, справа или слева. Таким образом, в результате одного сравнения область поиска сужается наполовину.
Цикл поиска повторяется до тех пор, пока искомый элемент не будет найден, или область поиска сузится до одного элемента, что будет свидетельствовать о том, что нужного элемента в массиве нет.
Функция, возвращающая номер позиции элемента в отсортированном массиве приведена ниже. Если элемент не найден, функция возвращает 0.
//Поиск позиции элемента в сортированом массиве
//x – элемент, позицию которого нужно найти
//а – упорядоченный массив, count – число элементов в нем
function FindPosInSortArray (x: integer; a: TArray100; count: integer): integer; var pos, left, right: integer;
begin
// left и right – левая и правая границы области поиска left := 1; right := count;
while left <= right do begin
// Позиция в середине области поиска pos:=(right + left) div 2;
if a[pos] = x then begin
{ элемент найден}
39
result := pos; exit;
end;
if x < a[pos]
then right := pos – 1 { элемент находится слева} else left := pos + 1; { элемент находится справа}
end;
// Элемент не найден result := 0;
end;
8.3.4Удаление элемента из отсортированного массива
Валгоритме удаления элемента из отсортированного массива можно использовать рассмотренную выше функцию для поиска индекса удаляемого элемента. После определения этого индекса, элемент удаляется путем сдвига влево на одну позицию всех элементов, находящихся за удаляемым. Значение переменной, в которой хранится количество элементов, уменьшается на единицу.
Процедура удаления элемента из отсортированного массива приведена
ниже.
//Удаление элемента из отсортированного массива
//x – элемент, который нужно удалить
//а – упорядоченный массив, count – число элементов в
нем
procedure DelFromSortArray (x: integer; var a: TArray100; var count: integer); var i, pos, left, right: integer;
begin
pos := FindPosInSortArray (x,a,count); if pos = 0 then exit;
count := count – 1;
for i := pos to count do a[i]:=a[i+1]; end;
8.4 ЗАДАНИЕ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
В лабораторной работе следует создать проект, в соответствии с
40
