Ассоциативный массив - Associative array
В Информатика, ассоциативный массив, карта, таблица символов, или толковый словарь является абстрактный тип данных состоит из коллекция из (ключ, значение) пары, так что каждый возможный ключ появляется в коллекции не более одного раза.
Операции, связанные с этим типом данных, позволяют:[1][2]
- добавление пары в коллекцию
- удаление пары из коллекции
- модификация существующей пары
- поиск значения, связанного с определенным ключом
Реализация ассоциативных массивов ставит проблема словаря, классическая задача информатики: задача проектирования структура данных который поддерживает набор данных во время операций «поиск», «удаление» и «вставка».[3]Два основных решения проблемы словаря: хеш-таблица или дерево поиска.[1][2][4][5]В некоторых случаях также возможно решить проблему, используя непосредственно адресованные массивы, деревья двоичного поиска, или другие более специализированные структуры.
Многие языки программирования включают ассоциативные массивы как примитивные типы данных, и они доступны в программные библиотеки для многих других. Память с адресацией по содержимому это форма прямой аппаратной поддержки ассоциативных массивов.
Ассоциативные массивы имеют множество приложений, в том числе такие фундаментальные. шаблоны программирования так как мемоизация и декоратор шаблон.[6]
Название происходит не от ассоциативное свойство известен в математике. Скорее, это происходит из-за того, что мы связываем значения с ключами.
Операции
В ассоциативном массиве связь между ключ и значение часто называют «отображением», и то же словесное отображение может также использоваться для обозначения процесса создания новой ассоциации.
Для ассоциативного массива обычно определяются следующие операции:[1][2]
- Добавить или вставить: добавить новый пара в коллекцию, сопоставляя новый ключ с его новым значением. Аргументами этой операции являются ключ и значение.
- Переназначить: заменить значение в одном из пары, которые уже находятся в коллекции, отображая существующий ключ на новое значение. Как и при вставке, аргументами этой операции являются ключ и значение.
- удалять или Удалить: удалить пара из коллекции, отключив данный ключ от его значения. Аргумент этой операции - это ключ.
- Искать: найти значение (если есть), связанное с данным ключом. Аргументом этой операции является ключ, а значение возвращается из операции. Если значение не найдено, некоторые реализации ассоциативного массива вызывают исключение, в то время как другие создают пару с данным ключом и значением по умолчанию для типа значения (ноль, пустой контейнер ...).
Часто вместо добавления или переназначения используется один набор операция, которая добавляет новый пара, если он еще не существует, в противном случае переназначает его.
Кроме того, ассоциативные массивы могут также включать в себя другие операции, такие как определение количества сопоставлений или построение итератор чтобы перебрать все сопоставления. Обычно для такой операции порядок, в котором возвращаются сопоставления, может определяться реализацией.
А Multimap обобщает ассоциативный массив, позволяя связывать несколько значений с одним ключом.[7] А двунаправленная карта - это связанный абстрактный тип данных, в котором сопоставления действуют в обоих направлениях: каждое значение должно быть связано с уникальным ключом, а вторая операция поиска принимает значение в качестве аргумента и ищет ключ, связанный с этим значением.
пример
Предположим, что набор кредитов, предоставленных библиотекой, представлен в структуре данных. Каждую книгу в библиотеке может проверять только один посетитель библиотеки одновременно. Однако один посетитель может проверить несколько книг. Таким образом, информация о том, какие книги проверены для каких клиентов, может быть представлена ассоциативным массивом, в котором книги являются ключами, а посетители - значениями. Используя обозначения из Python или JSON, структура данных будет такой:
{ "Гордость и предубеждение": "Алиса", "Грозовой перевал": "Алиса", "Большие Надежды": "Джон"}
Операция поиска по ключу «Большие надежды» вернет «Джон». Если Джон вернет свою книгу, это вызовет операцию удаления, а если Пэт извлечет книгу, это вызовет операцию вставки, что приведет к другому состоянию:
{ "Гордость и предубеждение": "Алиса", "Братья Карамазовы": "Пэт", "Грозовой перевал": "Алиса"}
Реализация
Для словарей с очень небольшим количеством сопоставлений может иметь смысл реализовать словарь, используя список ассоциаций, а связанный список сопоставлений. В этой реализации время выполнения основных операций со словарем линейно зависит от общего числа отображений; однако его легко реализовать, и постоянные факторы времени его работы невелики.[1][8]
Другой очень простой метод реализации, который можно использовать, когда ключи ограничены узким диапазоном, - это прямая адресация в массив: значение для данного ключа k хранится в ячейке массива А[k], или если для k тогда в ячейке хранится специальный контрольное значение что указывает на отсутствие сопоставления. Этот метод не только прост, но и быстр: каждая операция со словарем занимает постоянное время. Однако пространство, необходимое для этой структуры, составляет размер всего пространства ключей, что делает ее непрактичной, если пространство ключей невелико.[4]
Два основных подхода к реализации словарей: хеш-таблица или дерево поиска.[1][2][4][5]
Реализации хеш-таблиц
Наиболее часто используемая реализация ассоциативного массива общего назначения с хеш-таблица: an массив в сочетании с хэш-функция который разделяет каждый ключ на отдельную «корзину» массива. Основная идея хеш-таблицы заключается в том, что доступ к элементу массива через его индекс является простой операцией с постоянным временем. Следовательно, средние накладные расходы операции для хеш-таблицы - это только вычисление хеш-кода ключа в сочетании с доступом к соответствующему сегменту в массиве. Таким образом, хеш-таблицы обычно работают за время O (1) и в большинстве ситуаций превосходят альтернативные варианты.
Хеш-таблицы должны уметь обрабатывать столкновения: когда хеш-функция отображает два разных ключа в одну и ту же корзину массива. Два наиболее распространенных подхода к этой проблеме: отдельная цепочка и открытая адресация.[1][2][4][9] В отдельной цепочке массив не хранит само значение, а хранит указатель в другой контейнер, обычно список ассоциаций, в котором хранятся все значения, соответствующие хешу. С другой стороны, при открытой адресации, если обнаруживается хеш-коллизия, таблица ищет пустое место в массиве для хранения значения детерминированным образом, обычно путем просмотра следующей непосредственной позиции в массиве.
Открытая адресация имеет более низкий промах в кеше соотношение, чем отдельные цепочки, когда таблица в основном пуста. Однако по мере того, как таблица заполняется большим количеством элементов, производительность открытой адресации падает экспоненциально. Кроме того, при раздельной цепочке в большинстве случаев используется меньше памяти, если только записи не очень маленькие (меньше четырехкратного размера указателя).
Реализации дерева
Самобалансирующиеся бинарные деревья поиска
Другой распространенный подход - реализовать ассоциативный массив с самобалансирующееся двоичное дерево поиска, например AVL дерево или красно-черное дерево.[10]
По сравнению с хеш-таблицами эти структуры имеют как преимущества, так и недостатки. В худшем случае производительность самобалансирующихся двоичных деревьев поиска значительно лучше, чем у хеш-таблицы, с временной сложностью в нотация большой O из O (журнал п). Это контрастирует с хэш-таблицами, производительность которых в худшем случае включает в себя все элементы, совместно использующие одну корзину, что приводит к O (п) временная сложность. Кроме того, как и все бинарные деревья поиска, самобалансирующиеся бинарные деревья поиска поддерживают порядок своих элементов. Таким образом, обход его элементов следует шаблону от наименьшего к наибольшему, тогда как обход хеш-таблицы может привести к тому, что элементы будут расположены в случайном порядке. Однако хеш-таблицы имеют гораздо лучшую временную сложность в среднем случае, чем самобалансирующиеся деревья двоичного поиска O (1), и их производительность в худшем случае очень маловероятна при хорошем хэш-функция используется.
Стоит отметить, что самобалансирующееся двоичное дерево поиска может использоваться для реализации сегментов для хэш-таблицы, которая использует отдельную цепочку. Это позволяет выполнять постоянный поиск в среднем случае, но обеспечивает производительность O (log п). Однако это вносит дополнительную сложность в реализацию и может привести к еще худшей производительности для небольших хэш-таблиц, где время, затрачиваемое на вставку и балансировку дерева, больше, чем время, необходимое для выполнения линейный поиск на всех элементах связанного списка или аналогичной структуры данных.[11][12]
Другие деревья
Ассоциативные массивы также могут храниться в несбалансированных деревья двоичного поиска или в структурах данных, специализированных для определенного типа ключей, таких как радиксные деревья, пытается, Джуди массивы, или деревья ван Эмде Боаса, хотя возможности этих методов реализации в сравнении с хэш-таблицами различаются; например, деревья Джуди по-прежнему работают с меньшей эффективностью, чем хэш-таблицы, в то время как тщательно отобранные хеш-таблицы обычно работают с большей эффективностью по сравнению с адаптивными основами системы счисления с потенциально большими ограничениями на типы данных, которые они могут обрабатывать.[13] Преимущества этих альтернативных структур заключаются в их способности обрабатывать операции, выходящие за рамки базовых операций ассоциативного массива, такие как поиск сопоставления, ключ которого является наиболее близким к запрошенному ключу, когда сам запрос отсутствует в наборе сопоставлений.
Сравнение
Базовая структура данных | Искать | Вставка | Удаление | Заказал | |||
---|---|---|---|---|---|---|---|
средний | худший случай | средний | худший случай | средний | худший случай | ||
Хеш-таблица | О (1) | O (п) | О (1) | O (п) | О (1) | O (п) | Нет |
Самобалансирующееся двоичное дерево поиска | O (журнал п) | O (журнал п) | O (журнал п) | O (журнал п) | O (журнал п) | O (журнал п) | да |
неуравновешенный двоичное дерево поиска | O (журнал п) | O (п) | O (журнал п) | O (п) | O (журнал п) | O (п) | да |
Последовательный контейнер пары "ключ-значение" (например. список ассоциаций ) | O (п) | O (п) | О (1) | О (1) | O (п) | O (п) | Нет |
Заказанный словарь
Базовое определение словаря не требует порядка. Чтобы гарантировать фиксированный порядок перечисления, часто используются упорядоченные версии ассоциативного массива. Упорядоченный словарь имеет два смысла:
- Порядок перечисления всегда детерминирован для данного набора ключей путем сортировки. Это относится к реализациям на основе дерева, одним из представителей которых является
<map>
контейнер C ++.[14] - Порядок перечисления не зависит от ключа и вместо этого основан на порядке вставки. Так обстоит дело с «упорядоченным словарем» в .NET Framework и Python.[15][16]
Последний смысл упорядоченных словарей встречается чаще. Их можно реализовать с помощью список ассоциаций, или наложив двусвязный список поверх нормального словаря. Последний подход, который использовался CPython до версии 3.6, имеет то преимущество, что сохраняет потенциально лучшую сложность другой реализации.[17] CPython 3.6+ упорядочивает словари путем разделения хеш-таблицы на упорядоченный вставкой массив из k-v пар и разреженный массив («хеш-таблица») индексов.[18]
Языковая поддержка
Ассоциативные массивы могут быть реализованы на любом языке программирования в виде пакета, и многие языковые системы предоставляют их как часть своей стандартной библиотеки. В некоторых языках они не только встроены в стандартную систему, но и имеют специальный синтаксис, часто использующий индексы типа массивов.
Встроенная синтаксическая поддержка ассоциативных массивов была представлена в 1969 г. СНОБОЛ4, под названием «таблица». TMG предлагает таблицы со строковыми ключами и целочисленными значениями. МАМПЫ сделаны многомерные ассоциативные массивы, опционально постоянные, его ключевые структуры данных. SETL поддержал их как одну из возможных реализаций наборов и карт. Большинство современных языков сценариев, начиная с AWK и в том числе Rexx, Perl, Tcl, JavaScript, Клен, Python, Рубин, Язык Wolfram Language, Идти, и Lua, поддерживают ассоциативные массивы в качестве основного типа контейнера. На многих других языках они доступны как библиотечные функции без специального синтаксиса.
В Болтовня, Цель-C, .СЕТЬ,[19] Python, REALbasic, Swift, VBA и Delphi[20] они называются словари; в Perl, Рубин и Семя7 они называются хеши; в C ++, Ява, Идти, Clojure, Scala, OCaml, Haskell они называются карты (увидеть карта (C ++), unordered_map (C ++), и карта
); в Common Lisp и Windows PowerShell, они называются хеш-таблицы (поскольку оба обычно используют эту реализацию); в Клен и Lua они называются столы. В PHP, все массивы могут быть ассоциативными, за исключением того, что ключи ограничены целыми числами и строками. В JavaScript (см. Также JSON ) все объекты ведут себя как ассоциативные массивы со строковыми ключами, тогда как типы Map и WeakMap принимают произвольные объекты в качестве ключей. В Lua они используются как примитивный строительный блок для всех структур данных. В Visual FoxPro, они называются Коллекции. В Язык D также поддерживает ассоциативные массивы.[21]
Постоянное хранение
Многим программам, использующим ассоциативные массивы, в какой-то момент потребуется хранить эти данные в более постоянной форме, например, в компьютерный файл. Распространенным решением этой проблемы является обобщенная концепция, известная как архивирование или сериализация, который создает текстовое или двоичное представление исходных объектов, которое может быть записано непосредственно в файл. Чаще всего это реализуется в базовой объектной модели, такой как .Net или Cocoa, которая включает стандартные функции, преобразующие внутренние данные в текстовую форму. Программа может создать полное текстовое представление любой группы объектов, вызвав эти методы, которые почти всегда уже реализованы в базовом классе ассоциативных массивов.[22]
Для программ, использующих очень большие наборы данных, такое хранилище отдельных файлов не подходит, и система управления базами данных (DB) не требуется. Некоторые системы БД изначально хранят ассоциативные массивы, сериализуя данные, а затем сохраняя эти сериализованные данные и ключ. Затем отдельные массивы могут быть загружены или сохранены из базы данных с помощью ключа для ссылки на них. Эти хранилища "ключ-значение" использовались в течение многих лет и имеют такую же долгую историю, как более распространенные реляционная база данных (RDB), но отсутствие стандартизации, среди прочего, ограничивало их использование определенными нишевыми ролями. Для этих ролей в большинстве случаев использовались RDB, хотя сохранение объектов в RDB может быть сложной задачей, известной как объектно-относительное рассогласование импеданса.
После c. 2010, потребность в высокопроизводительных базах данных, подходящих для облачные вычисления а более точное соответствие внутренней структуры программ, использующих их, привело к возрождению рынка магазинов «ключ-значение». Эти системы могут хранить и извлекать ассоциативные массивы естественным образом, что может значительно повысить производительность в обычных рабочих процессах, связанных с Интернетом.
Смотрите также
использованная литература
- ^ а б c d е ж Гудрич, Майкл Т.; Тамассия, Роберто (2006), «9.1 Тип абстрактных данных карты», Структуры данных и алгоритмы в Java (4-е изд.), Wiley, стр. 368–371.
- ^ а б c d е Мельхорн, Курт; Сандерс, Питер (2008), «4 хеш-таблицы и ассоциативные массивы», Алгоритмы и структуры данных: базовый набор инструментов (PDF), Springer, стр. 81–98.
- ^ Андерссон, Арне (1989). «Оптимальные границы в словарной задаче». Proc. Симпозиум по оптимальным алгоритмам. Конспект лекций по информатике. Springer Verlag. 401: 106–114. Дои:10.1007/3-540-51859-2_10. ISBN 978-3-540-51859-4.
- ^ а б c d Кормен, Томас Х.; Лейзерсон, Чарльз Э.; Ривест, Рональд Л.; Штейн, Клиффорд (2001), «11 хеш-таблиц», Введение в алгоритмы (2-е изд.), MIT Press и Макгроу-Хилл, стр. 221–252, ISBN 0-262-03293-7.
- ^ а б Дицфельбингер, М., Карлин, А., Мельхорн, К., Мейер-ауф-дер-Хайде, Ф., Ронерт, Х. и Тарьян, Р. Е. 1994.«Динамическое идеальное хеширование: верхняя и нижняя границы» В архиве 2016-03-04 в Wayback Machine.SIAM J. Comput. 23, 4 (август 1994 г.), 738-761.http://portal.acm.org/citation.cfm?id=182370Дои:10.1137 / S0097539791194094
- ^ Гудрич и Тамассия (2006) С. 597–599.
- ^ Гудрич и Тамассия (2006) С. 389–397.
- ^ «Когда мне следует использовать хеш-таблицу вместо списка ассоциаций?». lisp-faq / часть2. 1996-02-20.
- ^ Кламмер, Ф.; Маццолини, Л. (2006), «Следопыты ассоциативных карт», Ext. Рефераты ГИС-l 2006 г., ГИС-I, стр. 71–74..
- ^ Джоэл Адамс и Ларри Найхофф.«Деревья в СТЛ».Цитата: «Стандартная библиотека шаблонов ... некоторые из ее контейнеров - шаблоны set
, map , multiset и multimap - обычно создаются с использованием особый вид самобалансирующееся двоичное дерево поиска называется красно-черное дерево." - ^ Кнут, Дональд (1998). Искусство программирования. 3: Сортировка и поиск (2-е изд.). Эддисон-Уэсли. С. 513–558. ISBN 0-201-89685-0.
- ^ Пробст, Марк (30.04.2010). "Линейный поиск против двоичного". Получено 2016-11-20.
- ^ Альварес, Виктор; Рихтер, Стефан; Чен, Сяо; Диттрих, Йенс (апрель 2015 г.). «Сравнение адаптивных оснований системы счисления и хеш-таблиц». 2015 31-я Международная конференция по инженерии данных IEEE. Сеул, Южная Корея: IEEE: 1227–1238. Дои:10.1109 / ICDE.2015.7113370. ISBN 978-1-4799-7964-6. S2CID 17170456.
- ^ "std :: map". en.cppreference.com.
- ^ "Класс OrderedDictionary (System.Collections.Specialized)". Документы MS.
- ^ "коллекции - Типы данных контейнеров - Документация Python 3.9.0a3". docs.python.org.
- ^ Димитрис Фасаракис Хиллиард. "словарь - как Python OrderedDict запоминает вставленные элементы?". Переполнение стека.
- ^ Димитрис Фасаракис Хиллиард. "Словари заказаны в Python 3.6+?". Переполнение стека.
- ^ "Класс Dictionary
" . MSDN. - ^ "System.Generics.Collections.TDictionary - RAD Studio API Documentation". docwiki.embarcadero.com. Получено 2017-04-18.
- ^ «Ассоциативные массивы, язык программирования D». Цифровой Марс.
- ^ "Руководство по программированию архивов и сериализаций", Apple Inc., 2012 г.