- •2 Статические и динамические объекты программ.
- •6 Вектор. Функциональная спецификация. Логическое описание и физическое представление.
- •14 Стек. Физическое представление (динамические объекты).
- •8 Очередь. Логическое описание и физическое представление (файл).
- •9 Очередь. Логическое описание и физическое представление (массив).
- •10 Очередь. Логическое описание и физическое представление (динамические объекты).
- •61 Обьектно-ориентированное программирование.
- •11 Стек. Функциональная спецификация
- •12 Стек. Логическое описание.
- •17 Линейный список. Физическое представление. Итераторы.
- •Void Create(List *l){ //создание списка
- •If(!res.Node) //если не удалось выделить память (массив заполнен)
- •19 Линейный список. Физическое представление (динамические объекты).
- •29 Рекурсивные структуры данных и их связь с алгоритмической рекурсией
- •1 Уровни описания структур данных.
- •Деревья. Двоичные деревья.
- •23 Двоичное дерево. Функциональная спецификация
- •24 Двоичное дерево. Логическое описание. Построение и визуализация
- •27 Особенности представления и обработки деревьев общего вида (преобразование к двоичному,...)
- •28 Деревья выражений
- •33 Поиск по образцу в последовательностях и таблицах.
- •34 Алгоритм Кнута-Морриса-Пратта
- •37 Таблицы с прямым доступом.
- •43 Турнирные сортировки.
- •46 Сравнение методов сортировки.
- •50 Абстрактные типы данных. Пример модуля лтд очередь.
- •52 Типизация языка программирования. Контроль типов.
- •53 Средства ослабления типового контроля в языке Паскаль. Преобразование и передача типов.
- •54 Полиморфизм операций, отношений и процедур. Родовые модули.
- •41 Обменные сортировки
17 Линейный список. Физическое представление. Итераторы.
Пока список не меняется, его удобно отображать на сплошной участок памяти (вектор). Сплошное представление списков обладает преимуществами для представления фиксированных списков или хронологических, добавление в которых всегда идет в конец: обращение к элементу списка может быть осуществлено за постоянное время за счет вычисления его адреса. При удалении элементов из сплошного списка образуются «дырки» (неиспользуемые фрагменты). Не существует простого способа пометить удаленные элементы, кроме сдвига всех элементов, начиная с удаленного, за N/2 шагов.
Для реализации сложных динамических структур данных цепного или сплошного характера принято использовать т. н. итераторы.
Для удобства организации списка и обеспечения единообразия доступа к нему определим объекты, обладающие функциями перехода от данного элемента списка к соседним. Зададим для них отношения равенства и неравенства. Два таких объекта равны тогда и только тогда, когда они указывают на один и тот же элемент списка. Также предоставим возможность чтения и записи элемента списка посредством введенных объектов. Такие объекты принято называть итераторами, и, конечно же, для них надо определить соответствующий тип данных.
Описание типа элементов двунаправленного списка, указываемых операторами:
struct Item
{
struct Item* prev ;
struct Item* next ;
T data;
};
Введение Not Equal() проясняет условия ветвления и
циклов и упрощает их, удаляя из них один унарный оператор. Функция Naxt() продвигает итератор к след.элементу списка. Prev() - зеркальное отражение ф-ии Naxt() . Ф-ия Fetch() нужна для чтения элемента списка, на который указывает итератор. Противоположная для Fetch() ф-ия Store() позволяет записать данные в элемент списка.
18 Линейный список. Физическое представление (массив). Если необходима большая быстродейственность и известна максимально возможная длинна списка (POOL_SIZE), то прибегают к более эффективной реализации списка на массиве.
{к перечисленным в п. 19 функциям необходимо дописать следующие}
const int POOL_SIZE = 100; //допустим макс. Размер– 100 элементов
typedef struct{
int size;
struct Item *top; //указатель напервый свободный элемент
struct Item data[POOL_SIZE + 1];
}List;
Void Create(List *l){ //создание списка
int I;
for(i = 0; I < POOL_SIZE,; i++)
l->data[i].next = &(l->data[i+1]); //односвязный список
l->data[POOL_SIZE – 1].next = 0; //терминальный элемент–нуль
l->head = &(l->data[POOL_SIZE]); //находится терминальный элемент здесь (в конце списка)
l->head->next = l->head->prev = l->head; //терминальный элемент
l->top = &(l->data[0]);
l->size = 0;
}
Iterator Insert(List *l, Iterator *i, const T){
Iterator res = { l->top}; //выделение памяти под новый элемент
If(!res.Node) //если не удалось выделить память (массив заполнен)
return Last(1);
l->top = l->top->next; //передвигаем top на следующую позицию
res.node->data = t;
res.node->next = i->node->next;// однонаправый список
res.node->prev = i->nod;
l->size++;
}
+ операции удаления элемента и уничтожения списка