Jump to content

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

(Перенаправлено из структуры данных Set )

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

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

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

Теория типов

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

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

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

Операции

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Реализации

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

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

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

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

my %elements = map { $_ => 1 } @elements;

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

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

Языковая поддержка

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

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

  • В C++ стандартная библиотека шаблонов (STL) предоставляет set класс шаблона, который обычно реализуется с использованием двоичного дерева поиска (например, красно-черное дерево ); SGI также предоставляет STL от hash_set класс шаблона, который реализует набор с использованием хеш-таблицы. C++11 поддерживает unordered_set класс шаблона, который реализован с использованием хеш-таблицы. В наборах ключами являются сами элементы, в отличие от упорядоченных контейнеров, где доступ к элементам осуществляется с использованием их (относительной или абсолютной) позиции. Элементы множества должны иметь строгий слабый порядок.
  • Стандартная библиотека Rust предоставляет общий HashSet и BTreeSet типы.
  • Java предлагает Set интерфейс для поддержки наборов (с HashSet класс, реализующий его с использованием хеш-таблицы), а SortedSet субинтерфейс для поддержки отсортированных наборов (с TreeSet класс, реализующий его с использованием двоичного дерева поиска).
  • Apple Foundation Платформа (часть 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 модуль, который реализует неизменяемые множества с использованием двоичных деревьев поиска. [9]
  • Пакет Tcl Tcllib предоставляет модуль set, который реализует структуру данных set на основе списков TCL.
  • Стандартная библиотека Swift содержит Set типа, начиная с Swift 1.2.
  • JavaScript Представлен Set как стандартный встроенный объект с ECMAScript 2015 [10] стандарт.
  • Стандартная библиотека Erlang имеет sets модуль.
  • Clojure имеет буквальный синтаксис для хешированных наборов, а также реализует отсортированные наборы.
  • LabVIEW имеет встроенную поддержку наборов, начиная с версии 2019.
  • Ада предоставляет Ada.Containers.Hashed_Sets и Ada.Containers.Ordered_Sets пакеты.

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

Мультисет

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

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

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

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

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

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

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

  • contains(B, x): проверяет, присутствует ли элемент x (хотя бы один раз) в сумке B
  • is_sub_bag(B1, B2): проверяет, встречается ли каждый элемент в пакете 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(B1, B2): возвращает пакет, содержащий только те значения, которые встречаются либо в пакете B 1 , либо в пакете B 2 , за исключением того, что количество раз, когда значение x встречается в полученном пакете, равно ( B 1 # x) + ( B 2 # х); иногда обозначается как B 1 B 2 .

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

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

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

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

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

SELECT expression1, expression2... FROM table_name...

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

MULTISET(SELECT expression1, expression2... FROM table_name...)

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

См. также

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

Примечания

[ редактировать ]
  1. ^ Например, в Python pick может быть реализован в производном классе встроенного set следующее:
    class Set(set):
        def pick(self):
            return next(iter(self))
    
  2. ^ Вставка элемента может быть выполнена за время O (1), просто вставив его в конец, но если избегать дублирования, это займет O ( n ). время
  1. ^ Питон: поп()
  2. ^ Управление и обработка сложных структур данных: Третий семинар по информационным системам и искусственному интеллекту, Гамбург, Германия, 28 февраля - 2 марта 1994 г. Труды, под ред. Кай против Удачи, Хайнц Марбургер, с. 76
  3. ^ Python Issue7212 : получить произвольный элемент из набора, не удаляя его; см . msg106593 относительно стандартного имени.
  4. ^ Ruby Функция № 4553 : добавление Set#pick и Set#pop
  5. ^ Индуктивный синтез функциональных программ: универсальное планирование, свертывание конечных программ и абстракция схемы посредством аналогичных рассуждений, Уте Шмид , Спрингер, 21 августа 2003 г., стр. 240
  6. ^ Последние тенденции в спецификации типов данных: 10-й семинар по спецификации абстрактных типов данных, совместный с 5-м семинаром COMPASS, С. Маргерита, Италия, 30 мая - 3 июня 1994 г. Избранные статьи, том 10, изд. Эджидио Астезиано, Джанна Реджио, Анджей Тарлецкий, с. 38
  7. ^ Руби: сгладить()
  8. ^ Ван, Томас (1997), Сортированная линейная хеш-таблица , заархивировано из оригинала 12 января 2006 г.
  9. ^ Стивен Адамс, « Эффективные наборы: балансирование » , Журнал функционального программирования 3 (4): 553-562, октябрь 1993 г. Проверено 11 марта 2015 г.
  10. ^ «Спецификация языка ECMAScript 2015 – ECMA-262, 6-е издание» . www.ecma-international.org . Проверено 11 июля 2017 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 82e320ed9f32985094bc0f52a84cc3e9__1715616420
URL1:https://arc.ask3.ru/arc/aa/82/e9/82e320ed9f32985094bc0f52a84cc3e9.html
Заголовок, (Title) документа по адресу, URL1:
Set (abstract data type) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)