Непересекающийся набор (алгоритм объединения-поиска) в PHP
Опубликовано: 16 февраля 2025 г. в 12:26:57 UTC
В этой статье представлена реализация на PHP структуры данных Disjoint Set, обычно используемой для Union-Find в алгоритмах минимального остовного дерева.
Disjoint Set (Union-Find Algorithm) in PHP
Disjoint Set (обычно используется для Union-Find или Disjoint Set Union) — это структура данных, используемая для управления разделением элементов на непересекающиеся (непересекающиеся) наборы. Она эффективно поддерживает две ключевые операции:
- Найти : определяет, к какому набору принадлежит элемент.
- Объединение : объединяет два множества.
Эта структура особенно полезна в алгоритмах минимального остовного дерева, таких как алгоритм Крускала.
У меня есть реализация алгоритма Крускала, используемая для генерации случайных лабиринтов, которая опирается на приведенную ниже реализацию PHP Disjoint Set для эффективного слияния множеств. Если вам интересно, вы можете увидеть ее в действии здесь: Генератор лабиринтов по алгоритму Крускала
В любом случае, вот моя реализация Disjoint Set на PHP:
{
private $parent = [];
private $rank = [];
public function __construct($size)
{
for ($i = 0; $i < $size; $i++)
{
$this->parent[$i] = $i;
$this->rank[$i] = 0;
}
}
public function find($x)
{
if ($this->parent[$x] != $x)
{
$this->parent[$x] = $this->find($this->parent[$x]);
}
return $this->parent[$x];
}
public function union($x, $y)
{
$rootX = $this->find($x);
$rootY = $this->find($y);
if ($rootX != $rootY)
{
if ($this->rank[$rootX] > $this->rank[$rootY])
{
$this->parent[$rootY] = $rootX;
}
elseif ($this->rank[$rootX] < $this->rank[$rootY])
{
$this->parent[$rootX] = $rootY;
}
else
{
$this->parent[$rootY] = $rootX;
$this->rank[$rootX]++;
}
}
}
}
Помимо создания лабиринтов для развлечения, структура данных Disjoint Set, безусловно, может быть использована и в реальных жизненных ситуациях.
Представьте себе, например, социальную сеть, которая хотела бы предлагать своим пользователям новых друзей, и предположим, что у нас уже есть шесть человек с такими дружескими отношениями:
- 1 и 2 — друзья.
- 2 и 3 — друзья.
- 4 и 5 — друзья.
- У 6 нет друзей.
Применив алгоритм Union-Find к этим отдельным группам, мы должны найти следующее:
- 1, 2 и 3 в одной группе.
- 4 и 5 во второй группе.
- 6 в третьей группе.
Исходя из этого, имело бы смысл предположить, что 1 и 3 должны стать друзьями, поскольку у них есть общий человек 2.
Конечно, в таком небольшом примере вы могли бы легко заметить этот факт и сами, но эффективность этого алгоритма позволяет масштабировать его на миллиарды людей и групп друзей.