Набор (абстрактный тип данных)

редактировать

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

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

A multiset - это особый вид набора, в котором элемент может фигурировать несколько раз.

Содержание

  • 1 Теория типов
  • 2 Операции
    • 2.1 Основные теоретико-множественные операции
    • 2.2 Статические наборы
    • 2.3 Динамические наборы
    • 2.4 Дополнительные операции
  • 3 Реализации
  • 4 Поддержка языков
  • 5 Мультимножество
    • 5.1 Мультимножества в SQL
  • 6 См. Также
  • 7 Примечания
  • 8 Ссылки

Теория типов

В теория типов, наборы обычно идентифицируются своей индикаторной функцией (характеристическая функция): соответственно, набор значений типа A {\ displaystyle A}A может обозначаться 2 A {\ displaystyle 2 ^ {A}}2 ^ {A} или P (A) {\ displaystyle {\ mathcal {P}} (A)}{\ mathcal {P}} (A) . (Подтипы и подмножества могут быть смоделированы с помощью типов уточнения, а наборы частных могут быть заменены на setoids.) Характеристическая функция F {\ displaystyle F }F из набора S {\ displaystyle S}Sопределяется как:

F (x) = {1, если x ∈ S 0, если x ∉ S {\ Displaystyle F (x) = {\ begin {case} 1, {\ t_dv {if}} x \ in S \\ 0, {\ t_dv {if}} x \ not \ in S \ end {case }}}F (x) = \ begin {cases} 1, \ t_dv {if} x \ in S \\ 0, \ t_dv {if} x \ не \ in S \ end {case}

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

Операции

Основные теоретико-множественные операции

Можно определить операции алгебры множеств :

  • union (S, T): возвращает объединение множеств S и T.
  • пересечение (S, T): возвращает пересечение множеств S и T.
  • разность (S, T): возвращает разность наборов S и T.
  • subset (S, T): предикат, который проверяет, является ли набор S subset набора T.

Статические наборы

Типичные операции, которые могут быть обеспечены структурой статического набора S:

  • is_element_of (x, S): проверяет, находится ли значение x в набор S.
  • is_empty (S): проверяет, является ли набор S пустым.
  • size (S)или мощность (S): возвращает количество элементов в S.
  • iterate (S): возвращает функцию, которая возвращает еще одно значение S при каждом вызове в произвольном порядке.
  • enumerate (S): возвращает список, содержащий элементы S в произвольном порядке.
  • build (x 1,x2,…, x n,): создает se t структура со значениями x 1,x2,..., x n.
  • create_from (collection): создает новую структуру набора, содержащую все элементы данной коллекции или все элементы, возвращаемые данный итератор.

Динамические наборы

Структуры динамического набора обычно добавляют:

  • create (): создает новую, изначально пустую структуру набора.
    • create_with_capacity (n): создает новую структуру набора, изначально пустую, но способную содержать до n элементов.
  • add (S, x): добавляет элемент x к S, если он отсутствует.
  • remove (S, x): удаляет элемент x из S, если он присутствует.
  • capacity (S): возвращает максимальное количество значений, которое может S hold.

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

Дополнительные операции

Есть много других операций, которые могут (в принципе) быть определены в терминах вышеизложенного, например:

  • pop (S): возвращает произвольное элемент S, удаляя его из S.
  • pick (S): возвращает произвольный элемент S. Функционально мутатор popможно интерпретировать как пару селекторов ( pick, rest),, где restвозвращает набор, состоящий из всех элементов, кроме произвольного. Может интерпретироваться в терминах iterate.
  • map (F, S): возвращает набор различных значений, полученных в результате применения функции F к каждому элементу S.
  • filter (P, S): возвращает подмножество, содержащее все элементы S, которые удовлетворяют заданному предикату P.
  • fold (A0, F, S): возвращает значение A | S | после применения A i + 1 : = F (A i, e)для каждого элемента e из S для некоторой двоичной операции F. F должен быть ассоциативным и коммутативным, чтобы это было четко определено.
  • clear (S): удалить все элементы S.
  • equal (S 1 ', S 2'): проверяет, равны ли два заданных набора (т. е. содержат ли все и только одинаковые элементы).
  • hash (S): возвращает хеш-значение для статического набора S, такое, что if равно (S 1, S 2), затем hash (S 1) = hash (S 2)

Другие операции могут быть определены для наборов с элементами специальный тип:

  • sum (S): возвращает сумму всех элементов S для некоторого определения «суммы». Например, по целому gers или real, его можно определить как fold (0, add, S).
  • collapse (S): для данного набора наборов вернуть объединение. Например, collapse ({{1}, {2, 3}}) == {1, 2, 3}. Может рассматриваться как своего рода sum.
  • flatten (S): для данного набора, состоящего из наборов и атомарных элементов (элементов, которые не являются наборами), возвращает набор, элементы которого являются атомарными элементами оригинала. набор верхнего уровня или элементы содержащихся в нем наборов. Другими словами, удалите уровень вложенности - например, collapse,, но разрешите атомы. Это можно сделать один раз или рекурсивно сгладить, чтобы получить набор только атомарных элементов. Например, flatten ({1, {2, 3}}) == {1, 2, 3}.
  • ближайший (S, x): возвращает элемент S, который является ближайшим по значению до x (по некоторой метрике ).
  • min (S), max (S): возвращает минимальный / максимальный элемент S.

Реализации

Наборы могут быть реализованы с использованием различных структур данных , которые обеспечивают различные временные и пространственные компромиссы для различных операций. Некоторые реализации предназначены для повышения эффективности очень специализированных операций, таких как ближайшийили union. Реализации, описанные как "общие", обычно стремятся оптимизировать операции element_of, addи delete. Простая реализация - использовать список , игнорируя порядок элементов и стараясь избегать повторения значений. Это просто, но неэффективно, поскольку такие операции, как членство в наборе или удаление элемента, выполняются за O (n), поскольку они требуют сканирования весь список. Наборы часто вместо этого реализуются с использованием более эффективных данных str структуры, в частности различные разновидности деревьев, попыток или хэш-таблиц.

Поскольку наборы можно интерпретировать как своего рода карту (с помощью функции индикатора), наборы являются обычно реализуется так же, как (частичные) карты (ассоциативные массивы ) - в этом случае значение каждой пары ключ-значение имеет тип единицы или контрольное значение ( как 1), а именно, самобалансирующееся двоичное дерево поиска для отсортированных наборов (которое имеет O (log n) для большинства операций) или хэш-таблицу для несортированных наборов (которая имеет O (1) средний случай, но O (n) худший случай для большинства операций). Сортированная линейная хеш-таблица может использоваться для предоставления детерминированно упорядоченных наборов.

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

my% elements = карта {$ _ =>1} @elements;

Другие популярные методы включают массивы. В частности, подмножество целых чисел 1..n может быть эффективно реализовано как n-битовый битовый массив, который также поддерживает очень эффективные операции объединения и пересечения. Карта Блума реализует набор вероятностно, используя очень компактное представление, но с небольшой вероятностью ложных срабатываний запросов.

Операции с логическим набором могут быть реализованы в виде более элементарных операций (pop, clearи add), но специализированные алгоритмы могут дают нижнюю асимптотическую оценку времени. Если наборы реализованы как отсортированные списки, например, наивный алгоритм для union (S, T)займет время, пропорциональное длине m из S, умноженной на длину n из T; тогда как вариант алгоритма объединения списков выполнит работу за время, пропорциональное m + n. Более того, существуют специализированные структуры данных набора (такие как структура данных union-find ), которые оптимизированы для одной или нескольких из этих операций за счет других.

Поддержка языков

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

  • . В C ++ Стандартная библиотека шаблонов (STL) предоставляет установить шаблонный класс, который обычно реализуется с использованием двоичного дерева поиска (например, красно-черное дерево ); STL SGI также предоставляет шаблонный класс hash_set, который реализует набор с использованием хэш-таблицы. C ++ 11 поддерживает класс шаблона unordered_set , который реализуется с помощью хеш-таблицы. В наборах сами элементы являются ключами, в отличие от последовательных контейнеров, где доступ к элементам осуществляется с использованием их (относительного или абсолютного) положения. Элементы набора должны иметь строгое слабое упорядочивание.
  • Java предлагает интерфейс Set для поддержки наборов (с HashSet , реализующий его с помощью хэш-таблицы), и субинтерфейс SortedSet для поддержки отсортированных наборов (с реализацией класса TreeSet он использует двоичное дерево поиска).
  • Apple Foundation framework (часть Cocoa ) предоставляет классы Objective-C NSSet , NSMutableSet , NSCountedSet , NSOrderedSet и NSMutableOrderedSet . API CoreFoundation предоставляют типы CFSet и CFMutableSet для использования в C.
  • Python имеет встроенный setи frozensetтипы начиная с 2.4 и начиная с Python 3.0 и 2.7, поддерживают непустые литералы набора с использованием синтаксиса фигурных скобок, например: {x, y, z}; пустые наборы должны быть созданы с помощью set (), поскольку Python использует {}для представления пустого словаря.
  • .NET Framework предоставляет универсальные классы HashSet и SortedSet , реализующие общий интерфейс ISet .
  • Библиотека классов Smalltalk включает Setи IdentitySet, используя равенство и идентичность для проверки включения соответственно. Многие диалекты предоставляют варианты для сжатого хранения (NumberSet, CharacterSet), для упорядочивания (OrderedSet, SortedSetи т. Д.) Или для слабые ссылки (WeakIdentitySet).
  • Стандартная библиотека Ruby включает модуль set , который содержит Setи SortedSetклассы, которые реализуют наборы с использованием хэш-таблиц, последняя позволяет выполнять итерацию в отсортированном порядке. Стандартная библиотека
  • OCaml содержит модуль Set, который реализует данные функционального набора структура с использованием двоичных деревьев поиска.
  • Реализация GHC Haskell предоставляет модуль Data.Set , который реализует неизменяемые наборы с использованием двоичных деревьев поиска.
  • Пакет Tcl Tcllib предоставляет модуль набора, который реализует структуру данных набора на основе списков TCL.
  • Стандартная библиотека Swift содержит тип Set, так как Swift 1.2.
  • JavaScript представил Set как стандартный встроенный объект со стандартом ECMAScript 2015.
  • Стандартная библиотека Erlang имеет модуль sets .
  • Clojure имеет буквальный синтаксис для хешированных наборов, а также реализует отсортированные наборы.
  • LabVIEW имеет встроенную поддержку наборов, начиная с версии 2019.

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

Multiset

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

Формально объекты в информатике могут считаться «равными» при некотором отношении эквивалентности, но все же различаться при другом отношении. Некоторые типы реализаций мультимножества будут хранить различные одинаковые объекты как отдельные элементы в структуре данных; в то время как другие свернут его до одной версии (первой встретившейся) и сохранят положительный целочисленный счетчик кратности элемента.

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

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

  • Стандартная библиотека шаблонов C ++ реализует как сортированные, так и несортированные мультимножества. Он предоставляет класс multiset для отсортированного мультимножества как своего рода ассоциативный контейнер, который реализует этот мультимножество с помощью самобалансирующегося двоичного дерева поиска .. Он предоставляет класс unordered_multisetдля несортированного мультимножества как своего рода неупорядоченных ассоциативных контейнеров, которые реализуют этот мультимножество с использованием хэш-таблицы . Несортированный мультимножество является стандартным для C ++ 11 ; ранее SGI STL предоставлял класс hash_multiset, который был скопирован и в конечном итоге стандартизован.
  • Для Java сторонние библиотеки предоставляют функциональность с несколькими наборами:
    • Apache Commons Collections предоставляет интерфейсы Bag и SortedBagс реализацией таких классов, как HashBagи TreeBag.
    • Google Guava предоставляет интерфейс Multiset с реализацией таких классов, как HashMultiset и TreeMultiset .
  • Apple предоставляет NSCountedSet как часть Cocoa, а также CFBag и CFMutableBag как часть стандартной библиотеки CoreFoundation.
  • Python включает collections.Counter , который похож на мультимножество.
  • Smalltalk включает в себя класс Bag, экземпляр которого может быть создан для использования идентичности или равенства в качестве предиката для теста включения.

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

Типичные операции с мешками:

  • contains (B, x): проверяет, присутствует ли элемент x (хотя бы один раз) в мешке B
  • is_sub_bag (B 1, B 2): проверяет, встречается ли каждый элемент в пакете B 1 в B 1 не чаще, чем в пакете B 2 ; иногда обозначается как B 1 ⊑ B 2.
  • count (B, x): возвращает количество раз, когда элемент x встречается в сумке B; иногда обозначается как B # x.
  • scaled_by (B, n): для натурального числа n возвращает мешок, содержащий те же элементы, что и мешок B, за исключением того, что каждый элемент, который встречается m раз в B, встречается n * m раз в полученном пакете; иногда обозначается как n ⊗ B.
  • union (B 1, B 2): возвращает пакет, содержащий только те значения, которые встречаются в любом из пакетов B 1 или мешок B 2, за исключением того, что количество раз, когда значение x встречается в результирующем пакете, равно (B 1 # x) + (B 2 # x); иногда обозначается как B 1 ⊎ B 2.

Мультимножества в SQL

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

SQL позволяет выбирать строки из реляционной таблицы: эта операция, как правило, дает мультимножество, если только ключевое слово DISTINCTне используется для того, чтобы все строки были разными, или выбор включает первичный (или потенциальный) ключ.

В ANSI SQL ключевое слово MULTISETможно использовать для преобразования подзапроса в выражение коллекции:

SELECT выражение1, выражение2... FROM имя_таблицы...

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

MULTISET (SELECT выражение1, выражение2... FROM table_name...)

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

См. Также

Примечания

Ссылки

Последняя правка сделана 2021-06-08 01:33:39
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте