Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 [ 138 ] 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

случаях можно было использовать более быструю целочисленную арифметику. - Прим. перев.)

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

Развитие и удешевление памяти с произвольным доступом уже в 50-х годах привело к пониманию того, что проблема поиска важна и интересна сама по себе. После многих лет жалоб на ограниченность пространства программисты столкнулись с таким изобилием, которое попросту не могли переварить и эффективно использовать.

Первые обзоры по проблеме поиска опубликованы А. И. Думи (А. I. Dumey), Computers 8z Automation 5,12 (December, 1956), 6-9; В. В. Петерсоном (W. W. Peterson), IBM J. Research к Development 1 (1957), 130-146; Э. Д. Бутом (A. D. Booth), Information and Control 1 (1958), 159-164; A. Ш. Дугласом (A. S. Douglas), Сотр. J. 2 (1959), 1-9. Более подробный обзор, посвященный проблемам сортировки, был сделан несколько позже Кеннетом Ю. Айверсоном (Kenneth Е. Iverson), А Programming Language (New York: Wiley, 1962), 133-158, и Вернером Букхольцем (Werner Buchholz), IBM Systems J. 2 (1963), 86-111.

В начале 60-х годов было разработано несколько новых процедур поиска, основанных на древовидных структурах (с ними мы встретимся немного позже). Исследования алгоритмов поиска ведутся и в настоящее время.

6.1. ПОСЛЕДОВАТЕЛЬНЫЙ ПОИСК

"Начать с начала и продолжать, пока не будет найден искомый ключ; затем остановиться." Эта последовательная процедура представляет собой очевидный путь поиска и может служить отличной отправной точкой для рассмотрения множества алгоритмов поиска, поскольку они основаны на последовательной процедуре. Мы увидим, что за простотой последовательного поиска скрывается ряд очень интересных, несмотря на их простоту, идей.

Вот более точная формулировка алгоритма.

Алгоритм S {Последовательный поиск (Sequential search)). Дана таблица записей i?2,..., Rn с ключами Ki,K2,..., Kjv соответственно. Алгоритм предназначен для поиска записи с заданным ключом К. Предполагается, что N > 1.

51. [Инициализация.] Установить г <- 1.

52. [Сравнение.] Если К = Ki, алгоритм заканчивается успешно.

53. [Продвижение.] Увеличить г на 1.

54. [Конец файла?] Если i < N, перейти к шагу S2. В противном случае алгоритм заканчивается неудачно.

Обратите внимание на то, что этот алгоритм может завершиться успешно (искомый ключ найден) и неудачно (искомый ключ отсутствует). Данное утверждение справедливо для большинства алгоритмов, рассматриваемых в этой главе.

MIX-программа пишется очень просто.



\Нет

SI. Инициализация

->S2. Сравнение

S3. Продвижение

S4. КонегЛ файла? J

Успешное завершение

Рис. 1. Последовательный поиск.

Неудачное завершение

Программа S (Последовательный поиск). Предположим, что Ki хранится по адресу KEY + г, а оставшаяся часть записи (Ri) - по адресу INFO + i. Программа использует гА = К, гИ = i - N.

START

Si. Инициализадия.

ENTl

i 1.

СМРА

KEY+N,1

S2. Сравнение.

SUCCESS

Выход, если К = Кг.

INCl

S3. Продвижение.

JINP

S4. Конец файла?

FAILURE EQU

Выход при отсутствии в таблице.

По адресу SUCCESS находится команда LDA INF0+N,1, которая помешает необходимую информацию в гА.

Анализ этой программы несложен. Очевидно, что время выполнения алгоритма S зависит от двух факторов:

С - количество сравнений ключей;

5 = 1 при успешном окончании поиска, О - при неудачном.

Программа S требует для работы 5С - 25 -Ь 3 единиц времени. Если при поиске успешно найден К = Ki, получим С = г, 5 = 1; таким образом, полное время составляет (5г -I- 1)и. С другой стороны, если поиск неудачен, мы получим С = N, 5 = О и общее время работы программы - {5N + 3)и. Если все ключи поступают на вход программы с одинаковой вероятностью, то среднее значение С в случае успешного поиска равно

l + 2 + ---+iV N + 1

N 2

При этом значение среднеквадратичного отклонения, естественно, достаточно велико и составляет около 0.289Л (см. упр. 1).

Данный алгоритм, несомненно, знаком всем программистам, но лишь некоторые из них знают, что этот способ - не самая лучшая реализация последовательного поиска! Небольшое изменение - и алгоритм выполняется существенно быстрее (если записей не слишком мало).

Алгоритм Q {Быстрый последовательный поиск). Перед вами тот же алгоритм, что и алгоритм S, однако в нем имеется дополнительное предположение о наличии фиктивной записи Rn+i в конце файла. Q1. [Инициализация.] Установить i +- 1 и Kn+i +- К.



Q2. [Сравнение.] Если К = Ki, перейти к шагу Q4.

Q3. [Продвижение.] Увеличить г на 1 и перейти к шагу Q2.

Q4. [Конец файла?] Если i < N, алгоритм заканчивается успешно; в противном случае алгоритм заканчивается неудачно (г = Л + 1).

Программа Q {Быстрый последовательный поиск), г А = К, гП = i - N.

START

01 START LDA К

02 STA KEY+N+1

03 ENTl -N

04 INCl 1

05 CMPA KEY+N,1

06 JNE *-2

07 JINP SUCCESS

08 FAILURE EQU *

1 QI. Инициализация.

1 Kn+1 K.

1 i-iO.

С +1 - S 0.3. Продвижение.

C + l-S 0.2. Сравнение.

C+l-S Переход к Q3, если К, ф К.

1 QA. Конец файла?

1 - 5 Выход при отсутствии в таблице.

Используя те же значения С и 5, что и в программе S, получим, что значение времени работы равно (4С - 45 + 10)и; таким образом, мы получаем вьшгрыш по сравнению с предыдущим алгоритмом в случае С > 6 для успешного поиска и N > 8 - для неудачного.

При переходе от алгоритма S к алгоритму Q использован важный ускоряющий принцип - при нескольких проверках во внутреннем цикле следует постараться свести их к одной.

Вот еще один способ сделать програ.мму Q еще быстрее.

Программа Q {Быстрый последовательный поиск), г А = К, rll = i - N.

START

LDA К

QI. Инициализация.

STA KEY+N+1

Kn+1 K.

ENTl -1-N

i -1.

INCl 2

-5 + 2)/2j

Q3. Продвижение (дважды).

CMPA KEY+N,1

\.{C

-5 + 2)/2j

Q2. Сравнение.

JE 4F

[.{C

-5 + 2)/2j

Переход к шагу Q4, если К = Кг-

CMPA KEY+N+1,1

[.{C

-5 + l)/2J

Q2. Сравнение (следующее).

JNE SB

\.{C

-5+l)/2j

Переход к шагу Q3, если К ф Ki+i

INCl 1

- 5) mod 2

Продвижение г.

JINP SUCCESS

Q4. Конец файла?

FAILURE EQU *

Выход при отсутствии в таблице.

Внутренний цикл дублирован, что позволяет избежать выполнения половины инструкций "г <- г -I-1", тем самым снижая затраты времени до

3.5С - 3.5S + 10 +

{С - S) mod 2

единиц времени. При работе с большими таблицами это сохраняет до 30% нашего времени. Такой способ ускорения применим ко многим существующим программам на языках высокого уровня [см., например, D. Е. Knuth, Computing Surveys 6 (1974), 266-269].

Можно воспользоваться другим улучшенным алгоритмом, если ключи расположены в порядке возрастания:



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 [ 138 ] 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262