Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 10.doc
Скачиваний:
0
Добавлен:
06.12.2019
Размер:
152.58 Кб
Скачать

Лекция 10

6.4. Простейшие алгоритмы

6.4.1. Поиск

6.4.1.1. Линейный поиск

В массиве A: array[iMin..iMax] of ТИП найти элемент равный B.

Листинг. Алгоритм линейного поиска

i:=iMin;

while (i<iMax) and (A[i]<>B) do i:=i+1;

Цикл while завершит свою работу либо при нахождении элемента равного B, либо при переборе всех элементов массива.

На каждом шаге цикла выполняется две проверки. Для упрощения проверок в конец массива A: array[iMin..iMax+1] of ТИП добавляется барьер - элемент равный B.

Листинг. Алгоритм линейного поиска с барьером

i:=iMin; A[iMax+1]:=B;

while A[i]<>B do i:=i+1;

Завершение работы цикла гарантировано, т.к. элемент B в массиве всегда есть. Ожидаемое число шагов – N/2.

6.4.1.2. Поиск делением пополам

В упорядоченном массиве A: array[iMin..iMax] of ТИП найти элемент равный B.

Листинг. Алгоритм поиска деления пополам

A1:=iMin; A2:=iMax; Ok:=false;

while (A1<=A2) and not Ok do

begin

m:=(A1+A2) div 2;

if A[m]=B then Ok:=true

else

if A[m]<B then A1:=m+1 else A2:=m-1;

end;

Листинг. Упрощенный алгоритм поиска деления пополам

A1:=iMin; A2:=iMax;

while A1<A2 do begin

m:=(A1+A2) div 2;

if A[m]=B then begin

A1:=m; A2:=m;

end

else

if A[m]<B then A1:=m+1 else A2:=m;

end;

Завершение работы цикла гарантировано, т.к. A1<m<A2, A1 – увеличивается, A2 - уменьшается. Ожидаемое число шагов – logN.

6.4.1.3. Поиск в массиве строк

В массиве упорядоченных строк AStr: array[iMin..iMax] of string найти строку St: string.

Воспользуемся поиском деления пополам:

Листинг. Поиск в массиве строк

A1:=iMin; A2:=iMax;

while A1<A2 do

begin

m:=(A1+A2) div 2; i:=0;

while (AStr[m,i]=St[i]) and (St[i]<>#0) do i:=i+1;

if AStr[m,i]<St[i] then A1:=m+1 else A2:=m;

end;

if A2<iMax then begin

i:=0;

while (AStr[A2,i]=St[i]) and (St[i]<>#0) do i:=i+1;

end;

6.4.1.4. Прямой поиск строки

В строке s: string[N] найти строку s0: string[M].

Листинг. Прямой поиск строки

i:=0;

repeat

i:=i+1; j:=1;

while (j<M) and (s[i+j-1]=s0[j]) do j:=j+1;

until (j=M) or (i=N-M);

6.4.2. Сортировка

6.4.2.1. Пузырьковая сортировка

Отсортировать массив A: array[iMin..iMax] of ТИП.

Листинг. Пузурьковая сортировка.

for i:=iMin+1 to iMax do

for j:=iMax downto i do

if A[j-1]<A[j] then

begin

t:=A[j-1]; A[j-1]:=A[j]; A[j]:=t;

end;

6.4.2.2. Шейкерная сортировка

Оптимизация предыдущего алгоритма включает в себя следующее:

  • массив можно считать уже упорядоченным, если на последнем проходе не было ни одной перестановки элементов;

  • сравнение пар элементов можно производить только до места последней перестановки: раз не было перестановок, значит – дальше элементы упорядочены;

  • при прохождении массива слева направо (снизу вверх) поднимается легкий пузырек. Почему бы не двигаться по массиву в обратном направлении – сверху вниз, опуская тяжелый пузырек?

Эти моменты учтены в шейкер-сортировке (от англ. shake – трясти), приведенной в листинге 7.6.

Листинг. Шейкерная сортировка.

procedure SortShaker;

var

j,L,left,right: integer;

tmp : integer;

last : integer; // место последней перестановки

begin

L:=Length(A);

left:=1; right:=L-1; last:=L-1;

repeat

for j:=right downto left do //поднимаются легкие пузырьки

if a[j-1]>a[j] then begin

tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp;

last:=j

end;

left:=last+1; // запомнили место последней перестановки

for j:=left to right do //опускаются тяжелые пузырьки

if a[j-1]>a[j] then begin

tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp;

last:=j

end;

right:=last-1; // запомнили место последней перестановки

until left>right;

end; //Shaker