<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=185.79.217.61&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=185.79.217.61&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/185.79.217.61"/>
		<updated>2026-04-06T23:03:14Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=66257</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=66257"/>
				<updated>2018-09-27T08:54:25Z</updated>
		
		<summary type="html">&lt;p&gt;185.79.217.61: оформление&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt;&lt;br /&gt;
Для любого элемента множества представитель всегда одинаковый. Поэтому чтобы проверить принадлежность элементов &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; одному множеству достаточно сравнить &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы объединить множества &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, надо изменить все &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt;, равные номеру множества &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt;, на номер &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;. Тогда &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
 '''struct''' SetItem &lt;br /&gt;
     '''int''' data       &lt;br /&gt;
     '''SetItem''' head&lt;br /&gt;
     '''SetItem''' next&lt;br /&gt;
     '''SetItem''' tail&lt;br /&gt;
&lt;br /&gt;
 '''SetItem''' s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].head = s[i]         &lt;br /&gt;
         s[i].tail = s[i]&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
&lt;br /&gt;
 '''int''' find('''SetItem''' x):                        &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&lt;br /&gt;
 '''func''' union('''SetItem''' x, '''SetItem''' y): &amp;lt;font color=green&amp;gt; // &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; {{ --- }} элементы множеств&amp;lt;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y                         &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail                         &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null                         &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D0%BA%D0%B0%D1%8E%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2 Википедия {{---}} Система непересекающихся множеств]&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Структуры данных]]&lt;/div&gt;</summary>
		<author><name>185.79.217.61</name></author>	</entry>

	</feed>