centos php mcrypt_資料結構PHP 並查集(Union Find)
阿新 • • 發佈:2020-12-23
技術標籤:centos php mcryptphp 7 class 初始化 銷燬php 7.4 bcmathphp class not foundphp headers already sentphp rsa sha256
這篇文章主要介紹一下並查集
,並查集
支援合併(Union)
和查詢(Find)
兩種操作,其中合併(Union)
表示把兩個不相交的集合合併為一個集合,查詢(Find)
表示查詢兩個元素是否在同一個集合中。
1.並查集(Union Find)示意圖
並查集的特點是兒子
節點指標指向父親:
2.並查集(Union Find)合併
如下圖所示,假設並查集中每個元素都不屬於其他集合,下面給出初始指向示意圖:
Tips:若要查詢兩個元素是否
相連
,可以找到兩個元素分別對應的根節點元素值是否相等,若相等,則判斷兩個元素屬於同一個集合。
3.並查集(Union Find)簡單的程式碼示例
3.1 PHP程式碼定義
下面是一個Union Find
類,__construct
建構函式初始化資料,如傳入size=20
,那麼$parent
中會初始化0~19
個指向自己
的節點元素:
<?php require 'UF.php';class UnionFind implements UF{private $parent = [];private $size;/**
* 初始化並查集
* UnionFind constructor.
* @param int $size
*/public function __construct(int $size){$this->size = $size;for ($i = 0; $i < $size; $i++) {$this->parent[$i] = $i;
}
}/**
* 返回並查集大小
* @param int $p
* @param int $q
* @return int
*/public function getSize(int $p, int $q): int{return $this->size;
}/**
* 查詢p對應的集合編號
* @param int $p
*/public function findRoot(int $p){if ($p < 0 && $p >= $this->size) {echo "404";exit;
}
$v = $this->parent[$p];while ($v != $p) {
$v = $this->parent[$v];
}return $v;
}/**
* 判斷兩個元素是否屬於同一個集合
* @param int $p
* @param int $q
* @return bool
*/public function isConnected(int $p, int $q): bool{
print_r([$p, $q, $this->findRoot($p), $this->findRoot($q)]);return $this->findRoot($p) == $this->findRoot($q);
}/**
* 合併兩個元素
* @param int $p
* @param int $q
*/public function unionElements(int $p, int $q): void{
$pRoot = $this->findRoot($p);
$qRoot = $this->findRoot($q);if ($pRoot != $qRoot) {$this->parent[$pRoot] = $qRoot;for ($i = 0; $i < $this->size; $i++) {if ($this->parent[$i] == $pRoot) {$this->parent[$i] = $qRoot;
}
}
}
}
}
Tips:程式碼中的合併預設`$p` 指向`$q` ,可優化成基於
根節點元素所包含元素總數
來決定合併方式的,元素少
根節點會被合併到元素多
的節點上,還可以根據並查集的深度
來決定誰被合併。
3.2 輸出演示
<?php require 'UnionFind.php';
$size = 10000;
$uf = new UnionFind($size);
$m = 500;for ($i = 0; $i < $m; $i++) {
$a = mt_rand(0, $size - 1);
$b = mt_rand(0, $size - 1);
$uf->unionElements($a, $b);
}
var_dump($uf->isConnected(50,100)); //判斷 50 和 100是否相連
$size = 10000;
$uf = new UnionFind($size);
$m = 11000;for ($i = 0; $i < $m; $i++) {
$a = mt_rand(0, $size - 1);
$b = mt_rand(0, $size - 1);
$uf->unionElements($a, $b);
}
var_dump($uf->isConnected(50,100)); //判斷 50 和 100是否相連
輸出如下圖:
程式碼倉庫 :https://gitee.com/love-for-poetry/data-structure
掃碼關注愛因詩賢