В этом параграфе вы познакомитесь с множествами — структурами данных, в которых каждый элемент встречается не более одного раза. Вы узнаете, как устроены множества в Python и C++, какие бывают разновидности множеств и как различается поведение упорядоченных и неупорядоченных коллекций. Научитесь выполнять базовые операции — добавление, удаление, проверку наличия, объединение и пересечение.
Ключевые вопросы параграфа
- Чем множество отличается от списка и в каких случаях его удобнее использовать?
- Как реализованы множества в разных языках — упорядоченные и неупорядоченные?
- Какие операции над множествами поддерживаются и в чём их сложность?
Определение множества (set)
Следующей структурой данных, которую мы рассмотрим, будет множество (set). Множество представляет собой контейнер, содержащий неповторяющиеся элементы в произвольном порядке.
Обратите внимание
в стандартной библиотеке С++ реализовано упорядоченное множество, что накладывает свои особенности на вычислительную сложность некоторых операций.
Далее в данном параграфе мы будем разграничивать упорядоченные и неупорядоченные множества.
Кроме того, существует такое понятие, как мультимножество (multiset), которое может включать в себя несколько одинаковых элементов.
Вы можете посмотреть на различия между множеством и мультимножеством на рисунке ниже.
Внутренняя реализация множества осуществляется различными способами, включая использование хэш-таблицы, бинарного дерева поиска и других алгоритмов. В данном параграфе мы сосредоточимся на функциях, которые можно производить со множеством, а не на внутренней его реализации.
Основные операции со множеством:
- Добавление элемента в множество.
- Удаление элемента из множества.
- Проверка наличия элемента в множестве.
- Объединение двух множеств.
- Пересечение двух множеств.
- Разность двух множеств.
Рассмотрим основные операции со множеством на примере двух языков С++ и Python. В STL языка С++ реализовано упорядоченное множество, в то время как в Python — неупорядоченное множество.
Добавление элемента
Добавление элемента в множество можно произвести следующим образом.
1 my_set = {1, 2, 3}
2 my_set.add(2)
3 print(my_set)
4 my_set.add(4)
5 print(my_set)
В результате исполнения фрагмента кода выше на экран будет выведено две строки: 1 2 3 и 1 2 3 4. Сложность операции добавления элемента во множество в Python — , так как множество не упорядочено и не нужно искать позиции для его вставки.
В языке С++ добавление элемента может быть осуществлено следующим образом (не забудьте добавить #include<set> в начало вашего кода).
1 set<int> val = {6, 10, 5, 1};
2 val.insert(6);
3 val.insert(10);
4 val.insert(2);
5 cout << val.size();
В итоге на экран будет выведено 5. В случае реализации на С++ мы имеем дело с упорядоченным множеством, что накладывает дополнительные временные издержки. Асимптотическая сложность добавления элемента — .
Удаление элемента
Не менее важной операцией является операция удаления элемента из множества.
1 set<int> val = {6, 10, 5, 1};
2 val.erase(6)
3 cout << val.size();
Благодаря фрагменту кода выше произошло удаление элемента, поэтому на экране появится число 3. Сложность операции удаления в упорядоченном множестве — .
Рассмотрим удаление элемента из множества в Python:
1 my_set = {1, 2, 3}
2 my_set.remove(1);
3 print(len(my_set))
Размер множества после удаления элемента становится равным двум. Сложность операции удаления в неупорядоченном множестве — .
Другие операции
- Проверка наличия элемента в множестве предполагает просмотр элементов в нём. В случае неупорядоченного множества, реализованного на хэш-таблицах, сложность — О(1). Однако, при использовании упорядоченного множества сложность становится O(logn).
- Объединение множеств предполагает их слияние в единое множество. Например, пусть было два множества. Первое содержало элементы 1, 2 и 3, а второе 2, 3 и 4. В результате объединения получится множество, содержащее четыре элемента 1, 2, 3 и 4.
- Пересечение множеств представляет из себя поиск в двух множествах одинаковых элементов. Пусть первое множество содержит элементы 1, 2 и 3, а второе — 2, 3 и 4. Тогда пересечением множеств будут являться элементы 2 и 3.
- Разность двух множеств предполагает нахождение всех элементов из первого множества, за исключением тех, которые находятся во втором множестве. Пусть первое множество содержит элементы 1, 2 и 3, а второе — 2, 3 и 4. Тогда разностью множеств будет элемент 1.
Упражнение
Поработайте с двумя множествами А = {1, 3, 4, 5, 6}, B = {1, 2, 4, 6, 8, 9}. Для данных множеств найдите объединение, пересечение и разность.
Что дальше
Теперь вы умеете работать с множествами: добавлять и удалять элементы, проверять их наличие, объединять и находить пересечение. Вы узнали, что множества полезны, когда важна уникальность, а не порядок, и что разные реализации дают разную эффективность.
Далее — структура, где каждому ключу сопоставлено значение. Вы познакомитесь со словарями, научитесь использовать ассоциативные массивы и узнаете, в чём их сила.
А пока вы не ушли дальше — закрепите материал на практике:
- Отметьте, что урок прочитан, при помощи кнопки ниже.
- Пройдите мини-квиз, чтобы проверить, насколько хорошо вы усвоили тему.
- Перейдите к задачам этого параграфа и потренируйтесь.
- Перед этим — загляните в короткий гайд о том, как работает система проверки.
Хотите обсудить, задать вопрос или не понимаете, почему код не работает? Мы всё предусмотрели — вступайте в сообщество Хендбука! Там студенты помогают друг другу разобраться.
Ключевые выводы параграфа
- Множество — это структура, содержащая только уникальные элементы.
- В Python используется неупорядоченное множество, а в C++ — упорядоченное.
- Основные операции: добавление, удаление, проверка наличия, объединение и пересечение.
- Эффективность зависит от реализации: хеш-таблицы обеспечивают быстрые операции, но не сохраняют порядок.
