1つ、および検索セット:相互に関連する要素のコレクションを検索します
学習を34日間続ける;
マージ:2つのセット
をマージする検索:2つの要素が1つのセットにあるかどうかを判断する
1.配列father []を使用します
int father[N]; //表示元素i的最高父亲节点(根节点)
Father [i] = iの場合、iがそのコレクションのルートノード(最高点)であることを意味します
2.最初は、各要素はそれ自体の個別のコレクションです。father[i] = iとします。
for(int i = 0;i <= n;i++)
father[i] = i;
3.検索:各コレクションはルートノードを1つしか持つことができないため、各要素のルートノードはfather [i] = i;になるまで継続的に検索する必要があります。
int findFather(int x)
{
while (x != findFather(x)) //只要当前节点还不是根节点
{
x = father[x]; //元素等于自身父亲节点
}
}
4. 2つの要素がセットに含まれているかどうかを判断するには、2つのルートノードが同じであるかどうかを判断します。
bool judge(int a, int b)
{
if (father[a] == father[b]) //如果根节点一样
return true;
else
return false;
5.要素aと要素bをセットにマージするなど、2つの要素をセットにマージする操作は、father [findFather [a]] = findFather(b)またはその逆を設定するだけで済みます。
if(findFather(a) != findFather(b)) //如果两个元素不在一个集合中,合并集合
father[ findFather[a] ] = findFather(b); //更新a的根节点的父亲节点为b的根节点
2.パス圧縮:上記のユニオン検索セットは最適化されておらず、効率は低く低速です。父ノードを見つけるために振り返ると、時間計算量は10の5乗の場合はO(n)です。 、それは明らかに耐えられない
1.栗を取ります:fa [1] = 1、fa [2] = 1、fa [3] = 2、fa [4] = 3;
これは、次のように同等に変更できます。fa[1] = 1、fa [2] = 1、fa [3] = 1、fa [4] = 1;
同じクエリパス上のすべての親ノードと同等です。 set 。ルートノードを指すと、時間計算量はO(1)に減少します。
int findFather2(int x)
{
int a = x; //由于最后x要变成它的根节点的值,所以先备份它
while (x != findFather(x))
{
x = father[x];
}
while (a != father[a]) //再用x初始值循环一遍
{
int z = a; //由于a查找的过程又会被覆盖,每次用z来备份
a = father[a]; //先将当前节点变为其父亲节点
father[z] = x; //再将刚刚的节点的父亲节点改为根节点的值
}
}