КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Списочные структуры
Статическая реализация графов. Проблема фрагментации памяти. До сих пор в реализации абстрактных типов мы старались жёстко зафиксировать некоторую нумерацию компонентов этого типа, связав её с естественной нумерацией самого массива. Такой подход не позволяет эффективно реализовать характерные для динамических типов операции вставки и удаления компонентов. Это хронический дефект массивов даже в их основной роли – хранение последовательностей. Упражнение. Написать процедуры вставки и удаления символа и слова в тексте. Дилемма: Либо тратить на не имеющие логического смысла технические сдвиги – дефрагментацию памяти, либо мириться с дырками фрагментированной памяти. Начальная идея проста – ставить новые компоненты не в конец или начало памяти (массива), а на первое попавшее свободное место.
Проблема. Теперь порядок компонентов-хранителей последовательности не будет совпадать с естественным порядком, следовательно, его нужно запоминать отдельно. Самый популярный способ сделать это – использовать списковую структуру, в которой вместе с каждым значением компоненты (члена последовательности) хранится индекс (указатель – имя) – следующая компонента. 1 2 3 4 5 6 7 8
2 7 1 8 Æ
5 – индекс 1-й буквы Æ - специальное значение – признак конца списка. Второй вариант – функция предшествования. Получаем понятия прямого, обратного и двукратного списков.
succ succ последовательность одна, но автоматы разные. pred pred
Общая схема реализации автомата как списка. Атрибуты вершин графа. На каждую стрелку отдельное поле, хранящее указатель на вершину, к которой ведёт эта стрелка.
Светофор
1 2 3 4 5 6 7 8
5 7 3 7 5
type tIndex=1..nMax; tList=record content:array[tIndex] of tNode; head:tIndex; end; tNode=record info:tInfo; {Атрибуты вершины} next:tIndex; end; tGraphNode=record info:tInfo[tIndex] of tNode; left,right:tIndex; end; Варианты – перечень полей-указателей. Например, для бинарного дерева – left,right:tIndex. Либо массив-указатель, либо список. Новый способ требует больше памяти. Окупится ли «жертва» эффективной вставки и удаления? Убедимся в этом (оставим на время проблемы, связанные с обработкой кучи). Задача. Включить в список List компоненту x после компоненты.
procedure Include(var List:tList;x:tInfo;AfterPtr:tIndex); var NewPtr:tIndex; begin {Взять первый свободный индекс NewPtr из кучи} GetHeap(List,NewPtr); After NewPtr with List do ¯ ¯
begin content[NewPtr].next:=content[AfterPtr].next; content[AfterPtr].next:=NewPtr; content[NewPtr].info:=x; end; end;
Замечание: процедура Include корректно работает, если известна ссылка на предыдущую компоненту, после которой надо вставлять. Техническая проблема: она не может включать в пустой список. Не хочется писать отдельную процедуру для включения в пустой список. Проверять же непустоту списка в процедуре Include неэффективно. Решение: расширить тип Index до 0..nMax и при инициализации списка поставить в него фиктивную нулевую компоненту («болванчик» или «фантом»). procedure Init(List:tList); begin with list do begin content[0].next:=0; head:=0; end; {Инициализировать кучу} end; {Удаление элемента из списка, стоящего после компоненты AfterPtr}
procedure Exclude(var list:tList;AfterPtr:tIndex);
AfterPtr ¯ j
(удаление)
{Работает в предположении, что удалённая компонента существует} var ThisPtr:tIndex; begin with list do begin ThisPtr:=content[AfterPtr].next; content[AfterPtr].next:=content[ThisPtr].next; {Сборка мусора – возвратить освободившуюся компоненту в кучу} PutHeap(List,ThisPtr); end; end;
Дата добавления: 2014-01-05; Просмотров: 296; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |