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

Костюк - Основы программирования

.pdf
Скачиваний:
134
Добавлен:
30.05.2015
Размер:
1.3 Mб
Скачать

101

Иногда контекстный поиск можно выполнить гораздо быстрее. Пусть, например, текст содержит предложения на русском языке, и образцом является слово русского языка. Тогда совпадение может начинаться с такой буквы, которая является самой первой в тексте либо стоит после пробела или знака препинания.

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

Пример 5.6. Поиск слова d в символьном массиве S длиной n. Слова разде­ ляются пробелами и другими символами, не являющимися буквами или цифрами. Ре­ зультат: i – номер символа S[i], совпадающего с первой буквой слова. Если пол­ ного совпадения нет, то i=0.

 

 

m:=length(d); p:=0; j:=1;

 

while (p<2)and(j<=n-m+1) do

 

begin c:=S[j];

 

if p=0 then begin

 

if Y[ord(c)]=1 then

 

end begin d1:=c; p:=1; i:=j end

 

else begin

(5.17)

if Y[ord(c)]=1 then d1:=d1+c

else if scomp(d,d1)=0 then p:=2

 

else p:=0

 

end;

 

j:=j+1

 

end;

 

if p=0 then i:=0

 

else if (p=1)and(scomp(d,d1)<>0) then i:=0;

 

Для определения вида символа используется вспомогательный массив Y с опи­

санием, аналогичным таблице T (5.14). Элемент Y[i]=1, если символ с кодом i является буквой, и Y[i]=0, если символ с кодом i не является буквой.

Переменная p в алгоритме имеет смысл состояния процесса распознавания. Если p=0, то еще не начато выделение очередного слова, т.е. перед этим были обна­ ружены символы-разделители. Если p=1, то начато выделение слова и его началь­ ные символы помещены в переменную d1. Наконец, если полное выделенное слово совпало с образцом, то p=2 и цикл прекращается. Сравнение с образцом осуще­ ствляется функцией scomp. Дополнительное сравнение с образцом после цикла необходимо из-за того, что искомое слово может находиться в самом конце текста без последующего разделителя.

Алгоритм имеет трудоемкость порядка n. Действительно, основной цикл испол­ няется не более n раз. Внутри цикла обычно производится не более двух сравнений, и только в случае полного выделения очередного слова длиной l, на что предвари­ тельно потребуется l шагов основного цикла, будет выполняться сравнение с образ­

102

цом, на которое будет затрачено не более l шагов (в функции scomp). Таким об­ разом, количество шагов выделения очередного слова и его сравнения с образцом не больше, чем удвоенная длина этого слова.

Конец примера.

Пример 5.7. Распознавание группы слов в символьном массиве S длиной n. Слова-образцы записаны в массиве строк D, их количество – k.

p:=0; j:=0; while j<=n do

begin j:=j+1;

{проверка для последнего слова без разделителя в конце:} if j<=n then c:=S[j] else c:=' ';

if p=0 then begin

if Y[ord(c)]=1 then begin d1:=c; p:=1; i:=j

end end

else begin

if Y[ord(c)]=1 then d1:=d1+c (5.18)

else begin {слово выделено, поиск совпадения} l:=1; p:=0;

while l<=k do

if comp(d1,D[l])=0 then begin r:=k+1;

writeln(D[l],i) end end

end end;

Информация о каждом распознанном слове выводится в виде: 1) распознанное слово; 2) номер символа в тексте, с которого начинается слово.

В алгоритме сравнение по группе образцов производится последовательно, поэтому трудоемкость алгоритма в наихудшем имеет порядок n k, где k – количе­

ство слов-образцов. Трудоемкость можно уменьшить до

nélog kù , применив ди­

хотомический поиск выделенного слова в предварительно

упорядоченном массиве

слов-образцов.

 

Конец примера.

 

5.3 Информационные таблицы

103

Объект, как элемент множества, можно задать в виде записи (структуры) зна­ чений характеристик, которые могут быть различных типов (числовыми, символьны­ ми строками и др.). Такие характеристики называют полями или ключами. Множе­ ство объектов при этом задается в виде информационной таблицы, каждый столбец в которой определяет поле, а каждая строка является записью. В программе инфор­ мационную таблицу можно представить различными способами:

1)в виде набора массивов (для каждого поля используется отдельный массив);

2)в виде массива записей;

3)в виде списка записей.

Пусть, например, таблица T содержит поля A, B, C, различающиеся по типам данных. Тогда i–я запись в информационной таблице может представляться:

1)совокупностью элементов массивов {A[i], B[i], C[i]};

2)элементом массива записей T[i] с полями:

{T[i].A, T[i].B, T[i].C}; 3) элементом списка записей с полями {A, B, C}.

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

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

Пример 5.8. Задача "спортивное двоеборье". Результаты соревнований спортсме­ нов по двум видам сведены в следующую таблицу:

Фамилия

Результат по 1-му виду

Результат по 2-му виду

Требуется определить места, занятые спортсменами в двоеборье, по сумме мест в отдельных видах. Победитель определяется по минимальной сумме мест.

Пусть правила определения мест в двоеборье следующие:

1)если результаты по одному из видов у всех спортсменов различны, и эти ре­ зультаты упорядочить по возрастанию, то место по этому виду у спортсмена X рав­ но номеру спортсмена X в упорядоченном списке;

2)если результаты нескольких спортсменов по одному из видов одинаковы, то им следует приписать одинаковое среднее место по этому виду;

104

3) если у нескольких спортсменов сумма мест по обоим видам одинакова, то им следует приписать одинаковое среднее место по двоеборью.

Пусть входная таблица задана следующими массивами: F (Фамилия), R1 (Ре­ зультат по 1-му виду), R2 (Результат по 2-му виду). Количество записей в таблице задано в переменной n.

Для промежуточных вычислений зададим четыре дополнительных столбца во входной таблице:

Место по

Место по

Сумма мест по

Общее место по

1-му виду

2-му виду

двум видам

двум видам

Эти столбцы зададим следующими массивами: M1 (Место по 1-му виду), M2 (Место по 2-му виду), MS (Сумма мест по двум видам), M0 (Общее место по двум

видам). Кроме того, для косвенного упорядочения столбцов понадобится еще один целочисленный массив In (индексный). Пусть также все массивы (кроме F) в опи­

сании имеют тип mas, с элементами типа real.

Вцелом алгоритм расчета мест будет следующим: place(R1,M1,n); {вычисление мест M1 по по 1-му виду}

place(R2,M2,n);

{вычисление мест M2 по по 2-му виду}

 

for i:=1 to n do

{вычисление суммы мест M0}

(5.19)

MS[i]:=M1[i]+M2[i];

 

place(MS,M0,n); {вычисление мест M0 по по обоим видам}

 

В алгоритме используется процедура place, вычисляющая места по одному ре­ зультату.

Алгоритм процедуры place в массиве M вычисляет места спортсменов по од­ ному из результатов, размещенных в массиве R:

 

 

 

 

 

procedure place(R,M:mas;n:integer);

 

 

 

var i,ib,j:integer;

 

 

 

begin

 

 

 

ssort(R,In,n);

 

 

 

{косвенная сортировка с индексным массивом In}

 

 

 

for i:=1 to n do

 

(5.20)

 

if (i=n)or(R[In[i]]<>R[In[i+1]]) then

 

 

begin

 

 

 

for j:=ib to i do M[In[j]]:=(ib+b)/2;

 

 

 

ib:=i

 

 

 

end

 

 

 

end;

 

 

 

В алгоритме (5.20) используется процедура косвенной сортировки

ssort, фор­

мирующая индексный массив In.

 

 

105

Нетрудно видеть, что трудоемкость всего алгоритма определяется трудоемко­ стью используемого алгоритма сортировки, и может оцениваться как n log n .

Конец примера.

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

1)в каждой из входных таблиц определяется одно или несколько полей, которые однозначно определяют объекты универсума; такие поля, одинаковые для обеих та­ блиц, называют ключевыми;

2)выходная таблица содержит поля из обеих входных таблиц;

3)в случае, когда некоторый объект присутствует в виде записи в обеих входных таблицах, в выходной таблице для него формируется запись, содержащая значения из записей обеих входных таблиц;

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

Вариант 1. В выходной таблице соответствующая запись не формируется. Вариант 2. Если для некоторого объекта есть запись в 1-й таблице, но нет во 2-й,

то запись формируется, а если нет записи в 1-й таблице, то не формируется.

Вариант 3. Если для некоторого объекта есть запись во 2-й таблице, но нет в 1-й, то запись формируется, а если нет записи во 2-й таблице, то не формируется.

Вариант 4. Запись формируется, если для объекта есть запись хотя бы в одной из входных таблиц.

При формировании записи во втором-четвертом вариантах недостающие значе­ ния полей заполняются особым пропущенным значением.

Обозначим через A множество объектов, записи которых имеются в 1-й табли­ це, через B – множество объектов, записи которых имеются во 2-й таблице. Тогда в варианте 1 выходная таблица будет содержать записи пересечения множеств A B , в

варианте 2 – записи множества A, в варианте 3 – записи множества B, в варианте 4

– записи объединения множеств A U B .

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

Пример 5.9. Формирование общей таблицы результатов по двум видам для зада­ чи "спортивное двоеборье".

Результаты соревнований спортсменов по двум видам записаны в две отдельные таблицы, каждая с двумя полями. Первая таблица содержит фамилию спортсмена (массив F1) и результат по 1-му виду (массив R01); Вторая таблица – фамилию спортсмена (массив F2) и результат по 2-му виду (массив R02). Количество запи­ сей в 1-й таблице – n1, во 2-й таблице – n2. Это соответствует тому, что некото­ рые спортсмены могли участвовать только в одном из видов двоеборья.

sort2(F1,R01,n1);

{упорядочение 1-й входной таблицы}

106

 

 

 

sort2(F2,R02,n2);

{упорядочение 2-й входной таблицы}

 

i1:=1; i2:=1; n:=0;

{пересечение множеств}

 

while (i1<=n1)and(i2<=n2) do

(5.21)

if F1[i1]<F2[i2] then i1:=i1+1

 

else if F1[i1]>F2[i2] then i2:=i2+1

 

else begin n:=n+1;

 

 

F[n]:=F1[i1];R1[n]:=R01[i1];R2[n]:=R02[i1];

 

i2:=i2+1; i1:=i1+1

 

 

end;

 

 

Соединение таблиц в алгоритме (5.21) реализуется по варианту 1 (пересечение множеств), т.е. спортсмены, участвовавшие только в одном из видов, не могут пре­ тендовать на победу в двоеборье.

Используемая в алгоритме процедура sort2 упорядочивает символьные стро­ ки массива, заданного как первый параметр, с одновременной перестановкой элемен­ тов числового массива – второго параметра. Третий параметр задает размеры масси­ вов.

Конец примера.

Вопросы и задания

1.Написать алгоритмы преобразования представления множества из двоичного массива в упорядоченный список и обратно.

2.Как выполняется проверка принадлежности объекта множеству при различных способах задания множества, и какова ее трудоемкость?

3.Как выполняется добавление объекта в множество при различных способах задания мно­ жества, и какова его трудоемкость?

4.Как выполняется удаление объекта из множества при различных способах задания множе­ ства, и какова его трудоемкость?

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

6.Как вычисляются объединение, пересечение, разность и симметрическая разность мно­ жеств, заданных двоичными массивами, и с какой трудоемкостью?

7.Доказать правильность алгоритма (5.10), вычисляющего объединение множеств, заданных целочисленными упорядоченными массивами.

8.Доказать правильность алгоритма (5.11), вычисляющего пересечение множеств, заданных целочисленными упорядоченными массивами.

9.Написать алгоритмы вычисления разности и симметрической разности множеств, задан­ ных целочисленными упорядоченными массивами. Доказать их правильность.

10.Написать алгоритмы вычисления объединения, пересечения, разности и симметрической разности множеств, заданных целочисленными неупорядоченными массивами. Доказать правильность алгоритмов и определить их трудоемкость.

107

11.Доказать правильность алгоритма (5.12), вычисляющего объединение множеств, заданных упорядоченными списками.

12.Доказать правильность алгоритма (5.13), вычисляющего пересечение множеств, заданных упорядоченными списками.

13.Написать алгоритмы вычисления разности и симметрической разности множеств, задан­ ных упорядоченными списками. Доказать правильность алгоритмов.

14.Что означает лексикографический порядок символьных строк?

15.Для чего в алгоритме (5.15), выполняющем лексикографическое сравнение двух символь­

ных строк, используется таблица перекодировки? Доказать правильность алгорит­ ма (5.15).

16.Написать алгоритм лексикографического упорядочения массива символьных строк с ис­ пользованием таблицы перекодировки, взяв за основу какой-либо простой алгоритм сор­ тировки.

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

18.Используя алгоритм распознавания слов (5.18), написать и отладить программу, которая вводит массив символов (текст), выделяет в нем слова, состоящие только из букв (с отож­ дествлением заглавных и строчных букв) и формирует словарь из этих слов, как массив строк. В словаре все слова должны быть различными.

19.Используя алгоритмы (5.19), (5.20) и (5.21), написать и отладить программу, которая пол­ ностью решает задачу "спортивное двоеборье": вводит таблицу результатов спортсменов в отдельных видах, после чего вычисляет и выводит места спортсменов по сумме мест в двух видах соревнований.

Глава 6 Алгоритмы с графами и отношениями

6.1 Представление графов и отношений

Граф задается двумя множествами: множеством вершин и множеством ребер (дуг). Ребро (дуга) задается парой вершин (которые оно соединяет). Имеются различ­ ные виды графов:

1)неориентированные графы, в таких графах для ребер не важен порядок зада­ ния вершин в паре, если вершина i соединена ребром с вершиной j, то это то же самое, что вершина j соединена ребром с вершиной i;

2)ориентированные или орграфы, в таких графах дуга определяет порядок зада­

ния вершин в паре, если есть дуга из вершины i в вершину j, то дуга из вершины j

ввершину i может существовать, а может и не существовать;

3)взвешенные графы, в которых каждому ребру (дуге) приписывается вес, та­ кие графы могут быть как ориентированными, так и неориентированными.

Кроме того, в мультиграфе одну и ту же пару вершин могут соединять несколь­ ко различных ребер (дуг).

Отношение на конечном множестве можно представить в виде ориентированного графа, поэтому задачи для отношений можно переформулировать в виде задач для орграфов.

Представление графа списком ребер (дуг). Для задания множества вершин гра­ фа достаточно указать их количество, предполагая, что вершины перенумерованы на­ туральными числами 1, 2, …, n. В ориентированном графе дуги или в неориентиро­ ванном графе ребра можно задать списком (массивом) пар вершин, причем для ори­ ентированного графа важен порядок задания вершин в каждой из пар. Если граф взвешен, то дополнительно с каждой парой вершин задают вес ребра (дуги). Этот способ обычно используется для хранения информации о графе, в то же время он не слишком эффективен для использования в алгоритмах, в которых приходится много­ кратно просматривать ребра.

Представление графа матрицей смежности. Ребра (дуги) графа можно задать в виде квадратной матрицы смежности, элемент которой Mij = 1, если есть ребро, со­ единяющее вершины i и j (или дуга идущая из вершины i в j), и равен нулю в противном случае. Для неориентированного графа матрица смежности симметрична (Mij = Mji), так как каждое ребро представлено двумя элементами матрицы. Во взве­

109

шенном графе элемент матрицы равен весу ребра (дуги) или особому значению (бес­ конечности), если между соответствующими вершинами нет ребра (дуги).

Чтобы просмотреть все вершины, смежные по ребрам с вершиной i (или вер­ шины, в которые идут дуги из i), необходимо перебрать элементы i –й строки мат­ рицы. Для просмотра вершин, из которых идут дуги в вершину i, необходимо пере­ брать элементы i –го столбца матрицы.

Представление графа списками смежных вершин. Если число ребер графа с большим числом вершин n существенно меньше, чем n2, то в матрице смежности большинство элементов будут нулевыми, и трудоемкость алгоритмов, просматрива­ ющих все ребра, будет намного больше минимально возможной. Так, например, для плоского графа число ребер меньше, чем 3∙n, однако трудоемкость просмотра всех ребер по матрице смежности будет порядка n2.

В этом случае более эффективно представление графа в виде массива из n ука­ зателей и n списков вершин, таких, что i-й указатель ссылается на тот список, кото­ рый содержит номера вершин, смежных с i-й вершиной. На рис. 6.1 изображен при­ мер неориентированного графа и его представление списком ребер, матрицей смеж­ ности и списками смежных вершин.

 

1

 

 

(1,2)

1

1

2

3

4

5

6

 

7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3

(3,1)

 

1

1

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(2,3)

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4

 

 

3

1

1

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(4,3)

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

2

 

 

 

 

4

 

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

6

 

(5,6)

 

 

 

 

 

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

 

7

 

 

 

7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 6.1

В представлении графа списками смежных вершин указатели в массиве можно описать типом pel, как в алгоритме (3.21). Такое представление подходит как для

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

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

Каждый из списков является множеством смежных вершин. Алгоритмы поиска (5.2), вставки (5.3) и удаления (5.4) элементов для него описаны в разделе 5.1 для случая, когда списки упорядочены. При неупорядоченности списков просмотр в этих алгоритмах будет требовать в среднем вдвое больше шагов.

110

Рассмотрим формирование списков, задающих граф.

Пример 6.1. Пусть совокупность m ребер (дуг) графа из n вершин задана c по­ мощью массивов v1 и v2 следующим образом: в элементах v1[i], v2[i] запи­ саны номера вершин, соединенных между собой i–м ребром, i=1, …, m. Массив S

содержит n элементов, имеющих тип pel,

которые будут указателями на списки.

Вспомогательная переменная ps также имеет тип pel.

 

 

for k:=1 to n

do S[k]:=nil;

{обнуление указателей}

 

 

for i:=1 to m

do

{формирование списков}

 

 

begin new(ps); ps^.s:=v2[i];

 

 

k:=v1[i];

ps^.p:=S[k]; S[k]:=ps;

(6.1)

 

{формирование 2-го элемента для неориентированного графа:}

 

 

new(ps); ps^.s:=v1[i];

 

 

 

k:=v2[i];

ps^.p:=S[k]; S[k]:=ps

 

 

end;

 

 

 

В алгоритме (6.1) вначале обнуляются указатели в массиве S. Затем формиру­ ются списки номеров смежных вершин. Для неориентированного графа формируется по два элемента списка на каждое ребро, а для ориентированного – один элемент на каждую дугу. Трудоемкость обоих этапов алгоритма – линейная от числа вершин или ребер графа.

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

каждый из списков отсортировать по отдельности, используя, например, алгоритм (4.7).

Конец примера.

Представление графа массивом смежных вершин. Если списки номеров смежных вершин разместить подряд в общем для всех списков массиве, получим структуру, изображенную на рис. 6.2. Здесь все списки размещены в целочисленном массиве D, размер которого для неориентированного графа равен удвоенному числу

ребер, а для ориентированного – числу ребер. Эти списки могут быть упорядоченны­ ми для ускорения в них поиска. В массиве S размещены для каждого из списков ин­ дексы начала, а в массиве L – длины списков. Длина массивов S и L равна коли­

честву вершин графа. Если граф взвешенный, то необходим еще один массив (такой же длины, что и массив D) с весами ребер.