Опубликован: 06.10.2011 | Доступ: свободный | Студентов: 1678 / 90 | Оценка: 4.67 / 3.67 | Длительность: 18:18:00
Лекция 6:

Фундаментальные структуры данных, универсальность и сложность алгоритмов

< Лекция 5 || Лекция 6: 12345 || Лекция 7 >

5.5. Кортежи

Массивы однородны: в экземпляре ARRAY [T] все элементы принадлежат типу T или типу, совместимому с T. Кортежи (Tuples) подобны массивам, но они могут содержать значения разных типов. Рассмотрим объявление:

tup: TUPLE [number: INTEGER, street: STRING, resident: PERSON]
    

Возможные значения tup во время выполнения представляют последовательности из трех компонентов, первый из которых имеет тип INTEGER, второй – STRING, третий – PERSON, предполагая, что такой класс существует. Такие кортежи полезны в различных приложениях, отражая тот факт, что в некотором доме с номером number на некоторой улице street живет гражданин resident.

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

tup:= [99, "Rue de Rivoli", Louvre_museum_curator]         [7]
    
Листинг 5.7.
Термин tuple в английский пришел из математики, где тройки, четверки называются triple, quadruple и по аналогии n-tuple. На русском мы говорим двойка, тройка и по аналогии n-ка (энка), но в переводах чаще используется более благозвучный термин "кортеж", понимаемый как последовательность из n значений.

Как типы кортежи не столь интересны, как массивы, списки, хэш-таблицы, бинарные деревья поиска, каждый из которых характеризуется своим собственным способом хранения и получения данных, своей эффективностью, преимуществами и ограничениями. Для кортежей наиболее распространенная реализация основана на массивах (игнорируя информацию о специфике типов компонентов кортежа, его можно рассматривать как ARRAY[ANY], где ANY — это общий универсальный тип высокого уровня, с которым совместимы все возможные типы). Поэтому для характеристики сложности операций над кортежами можно использовать уже известную нам таблицу для массивов.

Операция Нотация Сложность Комментарий
Доступ к компоненту t.comp O(1) Смотри ниже о нотации
Замена компонента t.comp:= value O(1)
Вставка, удаление Неприменима

Интерес к кортежам в другом: этот механизм языка позволяет описать простым и ясным способом структуры данных без обращения к классам. В нашем примере 5.7, где задавалось значение кортежа в целом, теги – number, street, resident – не играли роли, но они важны для доступа к индивидуальным значениям.

После выполнения 5.7 tup.number имеет значение 99. Теги можно также использовать и для задания значений компонентам, поскольку они рассматриваются как атрибуты с ассоциированными командами-присваивателями, что позволяет писать такие операторы, как:

tup.resident:= some_person
    

Конечно, можно было бы обойтись без типа TUPLE, используя классы, такие как:

class CENSUS_RECORD feature
        number: INTEGER assign set_number
        street: STRING assign set_street
        resident: PERSON assign set_resident
        set_number (n: INTEGER) do number:= n ensure number = n end
        … set_street, set_resident like set_number …
end
    

Над переменной cr типа CENSUS_RECORD были бы допустимы те же операции, что и над tup: доступ к полю (cr.number), модификация поля (cr.resident:= some_person).

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

Заметим, что теги не влияют на тип кортежа, фактически, они не обязательны. Ранее определенный кортеж можно задать как TUPLE [a: INTEGER, b: STRING, x: PERSON ] или просто TUPLE [INTEGER,STRING, PERSON ], если нет необходимости обращаться к компонентам по имени.

Синтаксически такие типы выглядят как универсально порожденные типы, подобные LIST [T]. Действительно, концепции очень похожи, но формально не существует класса TUPLE, поскольку это потребовало бы задать его с произвольным числом параметров, в то время как универсальный класс имеет фиксированное число параметров (один параметр у классов ARRAY [G] и LIST [G], два в HASH_TABLE [G, KEY]). Для кортежных типов можно описать последовательности любой длины: TUPLE без параметров задает все последовательности, TUPLE [T] – последовательность по меньшей мере из одного элемента, первый из которых имеет тип T, и так далее.

Это замечание определяет свойство согласованности кортежных типов: можно присваивать выражение типа TUPLE [T, U, V] переменной того же типа или любого из следующих типов – TUPLE [T, U]; TUPLE [T]; просто TUPLE. Последний из них (не класс, как отмечалось, но тип) покрывает задание всех возможных кортежей.

< Лекция 5 || Лекция 6: 12345 || Лекция 7 >