Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по информатике.doc
Скачиваний:
118
Добавлен:
02.05.2014
Размер:
1.53 Mб
Скачать

Ссылочные реализации структур данных

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

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

Ссылочные реализации обладают двумя ярко выраженными недостатками: 1) для хранения ссылок требуется дополнительная память; 2) для доступа к некоторому элементу структуры необходимо сначала добраться до него, проходя последовательно по цепочке других элементов. Казалось бы, зачем нужны такие реализации?

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

Массовые операции

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

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

Списки

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

Списком называется некоторая последовательность элементов, связанных при помощи указателей.

Различают однонаправленный и двунаправленный списки (иногда говорят односвязный и двусвязный).

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

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

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

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

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

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

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

Каждый элемент списка (иногда называемый узлом) состоит из двух частей. Первая часть содержит данные, принадлежащие элемен­ту, и является информационной. Вторая часть содержит указатель и является справочной. Указатель определяет местоположение элемента списка, связанного с данным элементом. На рисунке приведен пример списка с элементами А, В, С и D.

Стрелка в данном списке обозначает связь элементов списка. Указатель (т. е. вторая часть элемента списка) элемента А опреде­ляет номер следующего элемента списка. Указатель элемента В показывает, что за ним следует элемент С и т. д. Отсутствие или нулевое значение указателя означает, что данный элемент явля­ется последним в списке.

Элементы в списке могут быть связаны посредством разных ука­зателей.

В однонаправленных списках для каждого элемента указатель задает местоположение следующего

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

При работе со списками используется, как правило, еще один Указатель, который определяет первый элемент списка.

Для представления однонаправленного списка в памяти компью­тера можно использовать двумерный массив List [2][maxlist], где maxlist — это количество элементов в списке. В данном двумерном массиве любой элемент List[0] [i] содержит значе­ние элемента списка, а в List[i] [i] находится указатель на сле­дующий элемент.

Двунаправленный список так же представляется в виде двумер­ного массива List[3] [maxlist]. В этом случае элемент списка расположен в List[0] [i], а в List[1] [i] и List[2] [i] находятся указатели, которые указывают соответственно на предыдущий и последующий элементы списка.