Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Реализация структурных типов.



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

Индекс i называется адресом значения Memory[i, l]. Понятно, что когда длина поля l заранее известна, то по значению i можно однозначно восстановить содержимое поля Memory[i, l]. Таким образом, каждое имя переменной имеет числовое значение - адрес начала поля соответствующей этой переменной.

Значения структурных типов представляется в виде совокупности полей. Так, массив array[1..n] of T - это последовательность n битовых полей, каждое длины Len(T) - т.е. некоторое битовое поле Memory[AdrA, L] длины L=Len(T)*n

Аналогично, запись record N1: T1; …; Nm: Tm end - последовательность m битовых полей разных длин Len(T1), …, Len(Tm) - т.е. снова некоторое битовое поле Memory[AdrRec, L] длины L= Len(T1)+…+Len(Tm). Нетрудно вычислить AdrRec+ Len(T1)+…+Len(Tk-1) - адрес начала поля, содержащего значение r. Nk и таким образом реализовать операцию доступа по имени, для каждого имени Nk.

 

 

Инф Списки, стеки, очереди и их применение.

Рассмотрим некоторые общие принципы реализации абстрактных типов на примере двух простых и естественных типов - стек и очередь.

Основным множеством типа является множество всех (конечных) последовательностей f произвольной длины LenF над некоторым базовым типом T - f Î Nà T, Dom(f)=[1..LenF], LenF Î N. Т.е. оба типа, вообще говоря, - динамические; в случае фиксированной длины можно говорить о статических.

Интуитивная " идея" стека - " тот, кто пришел последним, уходит первым" или идея магазинной памяти.

Операторы и функции определения стека.

Create(r) - создать пустой стек с именем r. Начиная работать в любом состоянии s, оператор доопределяет s, добавляя в него пару rà < > (< > - пустая последовательность)

Destroy(r) - обратная к Create операция - убирает из текущего состояния пару rà R. Имя r перестает существовать, доступ к стеку теряется.

Внимание - важно понимать, что эти операторы добавляют и удаляют имена, не значения - т.е. изменяют область определения состояния Dom(s).

Push(r, x) - добавить компоненту x в верхушку стека - начиная работать в состоянии rà R, cо стеком длины Len(R) Dom(R)=[1..Len(R)], этот оператор неявно доопределяет Dom(R) до [1..Len(R)+1] и осуществляет присваивание R[Len(R)+1]: =x.

Pop(r, x) - осуществляет присваивание x: =R[Len(R)] (кладет верхнюю компоненту стека в x) и сокращает Dom(R) до [1..Len(R)-1] (уничтожает верхушку стека).

Empty(r)= true » Len(R)=0 (т.е. стек пуст)

Интуитивная идея очереди - " тот, кто пришел первым, первым и уйдет"

Операторы и функции определения очереди.

Create(r), Destroy(r) - тождественны соответствующим стековым операциям.

Put(r, x) - Поставить В Очередь - добавить компоненту x (базового типа T) в конец очереди - начиная работать в состоянии rà R, cо очередью длины Len(R) Dom(R)=[n..m], этот оператор неявно доопределяет Dom(R) до [n..m+1] и осуществляет присваивание R[m]: =x.

Get(r, x) - Вывести Из Очереди - осуществляет присваивание x: =R[n] (кладет первую компоненту очереди в x) и сокращает Dom(R) до [n+1..m] (уничтожает начало очереди).

Предикат Empty(r) (очередь пуста) - тождественен соответствующему предикату над стеком.

Реализация стеков и очередей (псевдодинамическими) массивами.

Псевдодинамические массивы - последовательности переменной длины m, m£ MaxLen, где MaxLen - константа.

const MaxLen=100;

type tIndex=1..MaxLen;

tArray=array[tIndex];

tPseudoArray=

record content: tArray;

top: tIndex;

end;

Содержимому стеков сопоставляется содержимое массивов, а стековым операциям - соответствующие алгоритмы обработки массивов.

Обратимся к моделированию очередей. Определяются " псевдодинамические" массивы с двумя концами.

tPseudoArray2=

record content: tArray; {содержимое/компоненты массива}

start, finish: tIndex; {начало+1 и конец-1 массива -}

{начало правой кучи и конец левой кучи}

end; tQueue=tPseudoArray2;

Реализация операций - класть значения в конец, а брать - из начала массива - порождает частный случай проблемы динамического распределения памяти: Вводя в конец и выводя из начала массива значения компонент, мы весьма скоро можем оказаться в ситуации, когда свободной памяти много, а класть компоненты некуда! В этом частном случае ее нетрудно решить, объединяя две части кучи, мысленно рассматривая массив как кольцо.

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

Проблема ее фрагментированности (" проблема кучек" ):

необходимо сохранить некоторую последовательность f; но нет ни одной кучки, достаточной для хранения всех элементов последовательности f в естественном порядке; хотя совокупного объема свободной памяти для этого достаточно.

Необходимое и одновременно изящное решение - хранить f в виде функции F: Nà N´ T c произвольной (т.е. " дырявой" и не упорядоченной) областью определения Dom(F)= {n1 , n2.,..., nk}, такой, что

(*) F(n1)=< n2, f(1)>, F(n2)=< n3, f(2)>,.., F(ni)=< ni+1, f(i)>, … F(nk)=< nk+1, f(k)>

Такой способ хранения последовательностей называется списковой организацией памяти, или просто списком. По определению, список F хранит значения f и индекс следующего ее значения. Указатель n1 называют головой списка, указатель nk+1, не принадлежащий Dom(F) - признаком конца списка. Обычно, в качестве признака выделяют специальный " пустой" указатель 0, единственный смысл которого - ни на что не указывать.

Основные операции над списками - перечисление, вставка и удаление компонент - никак не используют арифметические операции на Dom(F), т.е. тот факт, Dom(F)Ì N, а лишь то, что они, в качестве имен, указывают (ссылаются) на значения. Это и делает возможным реализацию списков ссылочным типом.

type

tComponent=record value: T; next: p: pComponent end;

pComponent=^tComponent;

pList=pComponent;

Реализация стеков и очередей списками.

Общее решение проблемы распределения памяти в виде списков в реализации абстрактных линейных типов - поставить значениям стека список с одной, а очереди - с двумя активными компонентами.

 

10. Инф Алгоритмы полного перебора на примере задачи о перечислении всех правильных раскрасок графа.

Пусть T - множество значений некоторого порядкового типа, T={Первый< Второй< …Последний}, succ - соответствующая функция следования, а Seq(L)=Seq(T, L)=[1..L]à T - множество всех последовательностей длины L.

Лексикографический, или словарный порядок на Seq(L) определяется следующим образом. Пусть a, b Î Seq(n), a¹ b и N=N(a, b)=min {n: a(n) ¹ b(n)}- наименьший номер i, на котором они различаются. Тогда a считается меньшей b, если у а на N-ом месте стоит меньшая (в смысле порядка на T) компонента, чем у b: a< b »def a(N)< T b(N).

Алгоритм определения следующей последовательности.

Следующая(a)=b » найдется число N такое, что для всех i, i Î [1..N], b(i)=a(i), b(N)=succ(a(N)) и b(j)=Первый, для всех j, j Î [N+1..L]. N=max{i: a(i) ¹ Последний}.

a) Вынимай из конца последовательности а все последние (в T) значения, пока не найдешь меньшего значения с. Если такого значения с нет, то а - это последняя последовательность.

б) Положи в конец a значение succ(c)

в) Доложи в конец последовательности необходимое число первых значений.

Обработка последовательностей " с одного конца", реализуется в терминах стеков.

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

Задача о раскраске графа. Найти (" распечатать" ) все правильные раскраски произвольного графа с фиксированным числом вершин n в m цветов. Раскраска правильная, если никакие две соседние вершины не окрашены в один цвет.

Предварительный анализ

found=$ r Î tРаскраска (правильная(r))

где Правильная(r)= " i, jÎ Вершины (Соседи(i, j)à Цвет(r, i)¹ Цвет(r, j))


Поделиться:



Последнее изменение этой страницы: 2017-03-14; Просмотров: 448; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.029 с.)
Главная | Случайная страница | Обратная связь