そして、セットパス圧縮(C ++)を確認してください

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;		//再将刚刚的节点的父亲节点改为根节点的值
	}
}

後で:数日前の34日間の質問で54ポイントしか得られない理由がついにわかりました

おすすめ

転載: blog.csdn.net/Kyrie_irving_kun/article/details/114849966