Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции Бахты.doc
Скачиваний:
82
Добавлен:
12.02.2015
Размер:
654.34 Кб
Скачать

Нагруженное множество

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

Условимся обозначать тип нагрузки именем InfoType, а тип ключа – KeyType.

Рассмотрим методы, применимые к нагруженному множеству:

  1. Конструктор (constructor Init;) – по умолчанию создает пустое множество.

  2. Деструктор (destructor Done;) – уничтожает нагруженное множество.

  3. Сделать пустым (procedure DoEmpty;).

  4. Пусто (function IsEmpty : boolean;) – функция, возвращающая true если множество пусто, и false – если множество содержит элементы.

  5. Добавить (procedure Insert( key : KeyType; info : InfoType);)- добавляет элемент с ключом key и нагрузкой info.

  6. Удалить (procedure Delete(key : KeyType );) – удаляет элемент с ключом key.

  7. Принадлежит (function IsPresent (key : KeyType) : boolean;) – проверяет принадлежность элемента множеству.

  8. Взять (procedure Extract(var key : KeyType; var info : InfoType);)

  9. Доступ для чтения (procedure Get(key : KeyType; var info : Infotype);)- читает элемент с ключом key.

  10. Доступ для записи (procedure Put(key : KeyType; info : InfoType);)- изменяет элемент с ключом key.

Замечания к методам:

  • Если при дополнении элемента этот элемент уже присутствует, тогда изменяется его нагрузка.

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

  • Если при чтении требуемый элемент отсутствует, тогда одним из способов обработки исключительной ситуации является возвращение кода выполнения операции.

При сравнении методов обычного и нагруженного множества можно заметить, что методы нагруженного множества – это видоизмененные методы обычного плюс методы для чтения и записи.

Идеи реализации.

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

Замечания к реализации:

  • При реализации на основе битовой строки ключу сопоставляется номер в массиве указателей на нагрузку. Если элемент не принадлежит множеству, тогда соответствующий ключу указатель указывает на nil.

  • С аналогичными поправками реализуются остальные принципы.

Итераторы.

Определение:

Абстракция итерации:

Для любого элемента х принадлежащего Абстрактной Структуре Данных (АСД)

выполнять

|

|

| действие (х)

|

|

конец итерации.

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

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

Рассмотрим АСД – таблицу:

Итератор: по всем значениям индексов произвести некоторое действие с элементом (например, чтение этого элемента), отвечающим конкретной паре индексов.

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

Для повышения эффективности итераторов используют следующие приемы:

  • Включить в протокол АСД дополнительные методы итератора

А) стартовать итератор.

Б) прочитать элемент (с продвижением).

В) проверить закончились ли элементы.

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

  • Создать дружественный класс итератора

В этом случае итератор имеет прямой доступ к реализации структуры.

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

Замечания:

  • Необходимо включить в АСД метод инициализации класса итератора.

  • Необходимо переработать структуру файлов, так как для класса итератора могут быть необходимыми некоторые поля АСД.

Рассмотрим пример фрагментов итератора для односвязного списка:

{модуль итератора}

unit AEnum;

.

.

.

.

Type PEnumList1=^CEnumList1;

CEnumList1=object

Public

Constructor Init(Pstart,Pend : PLink);

Destructor Done; virtual;

Procedure ReadInfo (var x : Info);

Function IsNotEnd : boolean;

Private

Pt:PLink;

Pe:PLink;

.

.

.

{другие поля}

end;

Implementation

.

.

.

Constructor CEnumList1.Init;

Begin

Pt:=Pstart;

Pe:=Pend;

End;

Procedure CEnumList1.ReadInfo;

Begin

{. . .} – проверка существования следующего

x:=Pt^.Info;

Pt:=Pt^.Next;

End;

Function CEnumList1.IsNotEnd;

Begin

IsNotEnd:=(Pt=Pe);

End;

{модуль АСД (очередь)}

.

.

.

public

procedure StartEnum (var PEnum : pointer);

.

.

.

Implementation

Uses Aenum;

.

.

.

Procedure Queue.StartEnum;

Begin

New(PEnumList1(PEnum),Init(pb,nil);

End;

Использование итератора

.

.

.

Q.StartEnum(PIter);

While Piter^.IsNotEnd do

Begin

Piter^.ReadInfo(x);

{обработка значений х}

End;

Dispose(Piter,Done);

.

.

.

В классе AEnum можно также реализовать итераторы и для других реализаций.