Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги из ГПНТБ / Оперативные графические системы в автоматизации проектирования

..pdf
Скачиваний:
4
Добавлен:
19.10.2023
Размер:
6.87 Mб
Скачать

со списочной организацией, а также язык

LEAP, раз ра­

бота ниып с использованием этого метода,

применяются в

графических системах [5, 6].

 

6.3. СПИСОЧНАЯ СТРУКТУРА ДАННЫХ

Рассмотренные

в

предыдущих параграфах способы

организации данных

в

определенных случаях являются

эффективными как по расходу времени па поиск элемен­ тов, так и по затратам памяти для хранения их. Однако для задач, связанных с динамическим изменением моде­ ли, такие структуры оказываются неэффективными. Наплучшнп результат в этом случае дает исполь­ зование списочной структуры данных (с. с. д.), элементы которой располагаются произвольно в памяти ЭВМ п соединяются между собой при помощи адресов связи.

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

Семантику с. с. д. можно наглядно описать с помощью аппарата теории графов, представляя список направлен­ ным графом [7, 8]. Графом списочной структуры G=(X, Г) называется пара, состоящая из непустого множества вершин X и отображения Г множества X в X, представля­ ющего собой множество направленных дуг Н= {«/,}, ко­ торые соединяют между собой пары вершин графа. Мно­ жество вершин A={a'i, а'2, л'з, ..., Хи) такого графа отобра­ жают элементы или блоки данных, а дуги — связи эле­ ментов пли блоков.

По сложности организации и возможностям примене­

ний с. с. д. можно

разделить на простые и сложные.

К простым с. с. д.

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

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

Цепные списки. Определение цепного списка. Цепной

список определяется

конечным

направленным

графом

G=( A, U), последовательность

дуг которого

U— {u\,

 

а

 

 

 

д

 

 

Ц Е П

Ь

 

9

--- —©----—®----

 

Рмс. 6.5. Цепной список: а — представление цепного списка символов; б — граф цепного списка

Рис. 6.6. Представление цепного списка символов в памяти (несколь­ ко слов на блок)

а-2, .... и/,} образует единственный простой путь, а для вер­ шин справедливы следующие условия:

-----

1;

=

1.

Цепной список символов

(ЦЕПЬ)

и его отображение в

виде направленного графа представлены на рис. 6.5, а, б. Представление цепного списка в памяти. В том слу­ чае если элементы данных и адреса связи размещаются каждый в отдельной ячейке, их можно поместить в двух последовательных ячейках. Тогда список символов (ЦЕПЬ) можно разместить в памяти так, как показано

на рис. 6. 6.

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

171

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

Рис. 6.7. Представление цепного списка символов в памяти (одно слово па блок)

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

Наиболее

часто в структурах с цепными списками в

качестве адреса связи последнего элемента списка уста­

навливается 0.

В этом случае ни один из элементов цеп­

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

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

два раза

(рис. 6.7)

по сравнению со структурой на рис.

6.6 [9].

 

 

 

 

 

Возможно и такое размещение элементов, при кото­

ром данные помещаются

в первую ячейку, а соответст­

вующий

адрес связи —в ячейку N+1, причем N не обя­

зательно равно 1. Такой метод позволяет

выполнить об­

работку

цепных

списков

с

помощью

языков типа

ФОРТРАН. При этом определяются два массива:

 

INTEGER ELEMENT (5000),

 

 

 

POINTER

(5000),

 

172

ii каждая пара (элемент, адрес связи) определяется пу­ тем индексирования на одну п ту же величину :в обоих массивах.

В рассмотренных методах представления элементов цепных списков адрес связи указывал на следующий эле­ мент цепочки. Цепной список с таким адресом связи можно назвать однонаправленным. Поиск элементов в таком списке ведется в одном направлении до последнего элемента. Такая организация списка достаточно проста

а

6

Рис. 6.8. Двухнаправлеиный цепной список: а — представление двухнаправлениого цепного списка символов; 6 — граф двухнаправлепно-

го цепного списка

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

Двухнаправленный цепной список имеет два адреса связи на один элемент — прямой и обратный. Прямой адрес указывает на следующий элемент, обратный— на предыдущий элемент цепного списка. Двухнаправленный цепной список и его отображение в виде симметрическо­ го графа показаны на рис. 6.8, а, б.

С целью сокращения расхода памяти может оказать­ ся целесообразным использовать кольцевой список

173

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

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

а

Е

Рнс. 6.9. Кольцевой список: а — представление кольцевого списка

символов; о — граф кольцевого списка

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

Во всех рассмотренных представлениях цепных спис­ ков в качестве элементов списка использовались простые величины (символы). Однако возможно применить цеп­ ные списки для связи блоков памяти, содержащих боль­ шее количество данных. В том случае если блоки имеют фиксированную длину, список блоков не отличается от списка простых величин. Таким же образом может быть построен однонаправленный, двухнаправлевный п коль­ цевой цепной списки. В элемент такого списка (рнс. 6.10) включается заголовок, в котором указывается длина блока, характеристика данных и т. д.

174

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

АДРЕС СВЯЗИ

ЗАГОЛОВОК

ДАННЫЕ

Рис. 6.10. Блок цепного списка

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

ков. По этой причине необходимо

организовать область

свободных ячеек в цепной список,

называемый списком

свободных ячеек.

Элементы этого списка

имеют такую

же структуру, как п элементы

создаваемых списков. Из

списка свободных

ячеек берутся ячейки для построения

с. с. д., п в него

возвращаются освободившиеся ячейки.

Однако не всегда является

очевидным,

освободилась

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

При стирании элемента В в цепном списке 1 (рис. 6.11), т. е. изменении адреса связи в элемент Б, ячейки элемента В нельзя передать в список свободных ячеек, так как при этом будет разрушен цепной список 2.

Таким образом, возникает необходимость в разработ­ ке способов поиска действительно освободившейся памя-

тн п присоединения ее к списку свободных ячеек. Этот процесс носит название «чистка» памяти.

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

ски ссылаются на исключаемый элемент. Тогда необхо­ димо во всех списках изменить адреса связи, указываю­ щие на исключаемый элемент, а сам элемент присоеди­ нить к списку свободных ячеек. Однако иногда процесс изменения адресов является длительным и целесообраз­ но оставить элемент в списках, отметив его специальным признаком («ключом»), т. е. исключить элемент логи­ чески.

В большинстве случаев в с. с. д. существуют общие подсписки и известно, сколько и какие списки указывают на данный элемент. Для решения проблемы чистки памя­ ти в данном случае обычно используются три различных метода [10].

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

Второй метод предполагает наличие в блоке данных числа, показывающего, сколько раз на данный элемент

176

произведено ссылок. В процессе выполнения программы проверяется это число, и при равенстве его нулю элемент включается в список свободных ячеек. Этот метод носит название «подсчета ссылок». В каждом элементе цеп­ ного списка выделяется поле, в котором размещается счетчик ссылок, показывающий количество адресов свя­ зи, указывающих на данный элемент. Всякий раз, когда новый элемент включается в цепной список, его счетчик ссылок устанавливается в единицу. Если создается адрес связи, указывающий на уже существующий элемент, то счетчик ссылок этого элемента увеличивается на едини­ цу, при изменении или исключении адреса связи счетчик ссылок указываемого элемента уменьшается на единицу. Когда счетчик ссылок элемента уменьшился до нуля, этот элемент включается в список свободных ячеек, а счетчик ссылок того элемента, на который указывал адрес связи данного элемента, уменьшается на единицу.

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

Ш а г 1.

Отмечаются все нужные в данный момент

элементы.

Для этого все списки н подсписки структуры

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

те элементы,

которые остались неотмеченными (разряд

занятости равен нулю), являются ненужными.

Ш аг 2.

Заполняется список свободных ячеек. Для

этого сканируется вся область памяти, отведенная под структуру, и всякий раз, когда встречается неотмеченный элемент, он присоединяется к списку свободных ячеек; когда встречается отмеченный элемент, его разряд заня-

12. Зак. 218

177

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

Последний метод является универсальным способом чистки памяти, хотя и более длителен, так как требует просмотра всех элементов списков. Метод подсчета ссы­ лок выполняется быстрее, однако при этом увелнчнва-

Разряд занятости

Рис. 6.12. Цепной список символов до процесса уплотнения

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

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

В качестве примера рассмотрим один из возможных алгоритмов уплотнения, который можно применить для цепных списков с элементами одинакового размера. Ос­ новная идея алгоритма заключается в том, что размеще­ ние в одной области всех нужных элементов, а в другой ненужных осуществляется путем перемены их местами, причем в ячейку, где ранее находился перемещаемый элемент, ставится адрес той ячейки, в которую он пе­ ремещен. Произведем уплотнение цепного списка, имею­ щего элементы одинаковой длины и объединяющего че­ тыре символа ЦЕПЬ (рис. 6.12).

178

Пусть

элементы этого списка будут размещены

в области

памяти размером в 10 ячеек. Во время скани­

рования этой области на первом шаге чистки все элемен­ ты списка будут отмечены как нужные, т. е. разряд заня­ тости установлен в единицу. Все ненужные элементы будут иметь указатель занятости равный нулю (рис. 6.13, а). В процессе уплотнения используются две дополни­ тельные ячейки, назовем их ВЕРХ и НИЗ. Первоначаль­ но в ячейке ВЕРХ содержится адрес, указывающий на верхнюю ячейку области, а в ячейке НИЗ — на нижнюю ячейку области (рнс. 6.13, а). Затем путем последова­ тельного уменьшения на единицу содержимого ячейки ВЕРХ сканируется область памяти сверху вниз до тех пор, пока не встретится ненужный элемент; с помощью ячейки НИЗ сканируется область снизу вверх до нужно­ го элемента. Нужный элемент при этом помещается по адресу, указанному в ячейке ВЕРХ, а адрес этой новой ячейки (значение ячейки ВЕРХ) помещается в старую ячейку, указанную адресом в ячейке НИЗ, и процесс ска­ нирования продолжается (рис. 6.13, б, в). Первая фаза уплотнения оканчивается, когда значения адресов в ячейках ВЕРХ и HEI3 сравняются (рнс. 6.13, г). При этом в ячейке НИЗ содержится последний адрес блока нужных элементов. Во второй фазе сканируется область сверху до границы блока нужных элементов (адрес НИЗ), и вместо адресов связи тех элементов, которые указывают за границу этого блока (т. е. значение адре­ сов меньше, чем НИЗ”), подставляются адреса из старых ячеек, причем старые ячейки отмечаются как ненужные (рис. 6.13, Р). Из рис. 6.13, д видно, что после уплотнения первоначально разбросанные в памяти элементы цепно­ го списка оказались компактно упакованными в после­ довательные ячейки одного блока, а свободные (ненуж­ ные) элементы занимают ячейки другого блока.

Обработка цепных списков. При обработке списков одной из важных операций является хранение и поиск элементов в списочной структуре. Для того чтобы найти элемент в цепном списке, необходимо пройти по всей це­ почке адресов связи до нужного элемента. Этот элемент определяется своим идентификатором, записанным в определенном поле элемента. При включении элемента в цепной список адрес ячейки, в которую он записывает­ ся, не зависит от идентификатора элемента, а онреде-

12*

179

Соседние файлы в папке книги из ГПНТБ