Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Kurs_za_vtoroy_semestr_Abstraktnye_tipy_dannykh...doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
436.74 Кб
Скачать

Программирование и алгоритмические языки. Курс за второй семестр. Абстрактные типы данных.

Приближённые к реальности, но отсутствующие в данном языке программирования типы данных, называются абстрактными.

«Программы = алгоритмы (процедуры) + структуры данных»

Н. Вирт

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

Тип

Задача раскраски.

Выяснить, можно ли данную карту правильно раскрасить данным количеством цветов. Если да, то предъявить все возможные раскраски. Раскраска правильная, если никакие две соседние страны не окрашены в один цвет.

Делаем первые выводы относительно определения типа данных.

Type tСтраны = 1..n; {Можно взять произвольный порядковый тип}

tКарта = array [tСтраны,tСтраны] of Boolean; {На этом типе обязана быть определена единственная функция}

var карта: tКарта;

m:cardinal;

Можно: boolean;

Раскраска: tРаскраска; {Определение типа откладываем до определения операций, которые нужны в алгоритме}

Function Правильная (раскраска: tРаскраска):boolean;

{правильная:=i,jtСтраны (соседи (i,j)(i<j)  раскраска(i)  раскраска j)}

{Стрелка – логическая связь – «если, то»}

{правильная:= }

Begin

Result:=true;

i:=первая страна;

while (i<=последняя страна) and (Result) do

begin

j:=succ(i);

while (j<=последняя страна) and Result do

begin

if соседи (i,j) then if раскраска (i) = раскраска (j) then Result:=false;

else j:=succ(j);

end;

i:=succ(i);

end;

Begin

{Можно:= раскраска – tРаскраска - правильная}

можно:=false;

раскраска:=первая раскраска;

while not (конечная раскраска) do

Begin

If (правильная раскраска) then

Begin

Можно:=true;

Write (Правильная раскраска);

End;

Раскраска:=следующая раскраска;

End;

End.

Мы отождествляем тип tКарта с функцией “Соседи”, задавая её в виде булевского массива. Не забудь переименовать в алгоритме Соседи на Карта!

tРаскраска: tСтранаtЦвет

array[tСтрана] of tЦвет

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

Перечисление последовательностей фиксированной длины.

n циклов дали бы нужный порядок, но мы не можем выразить такой оператор синтаксически, однако это даёт идею того, в каком порядке можно перебирать последовательности (конечные функции) – в словарном (лексикографическом).

a=a1,…,an

b=b1,…,bn

a<b  ai0<bi0, где i0 – наименьший символ i такой, что aibi и i<i0 ai=bi

Procedure Следующая ({var Раскраска: tРаскраска;var Кончились:boolean});

{Выдаёт раскраску, следующую за данной, кладёт «Кончились» в true, если таковой нет}

Begin

Кончились:=false;

i:=последняя страна;

c:=раскраска[i];

while not Кончились and (раскраска[i]последний цвет) do

Begin

Раскраска[i]:=первый цвет;

i:=i-1;

кончились:=i=0;

if not Кончились then раскраска[i]:=succ(раскраска[i]);

end;

{Поддерживается быстрое вычисление конъюнкции}

Упражнение. Завершить первый вариант решения задачи.

Привлекательное своей простотой наше решение грешит единственным недостатком – оно неэффективно. Непосредственный выбор структуры данных под алгоритм игнорирует вопросы компактного хранения. Но основная сложность – эффективность по времени. Полный перебор раскрасок даёт (число цветов – число стран) – экспоненциальный алгоритм. Потратится много времени. Такие алгоритмы в программировании считаются практически невыполнимыми за реальное время.

Вопрос: нужно ли было писать такой алгоритм???

Ответ: несомненно, ДА!!!

Правильные программы имеет смысл улучшать. Преобразовывать программы эквивалентно проще, чем писать новые, но основной туш таков: достоинство плохих решений – простые решения универсальны и служат исходной точкой для решения очень широкого круга задач. Теория даёт простые решения.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]