データ構造5-4-1とクエリセット

1.コンセプト

ユニオン検索コレクションは、基本的にツリーの知識を使用します。セットの関連表現によく使用されます。一般的なバイナリツリーとは異なります。ユニオン検索コレクションは、親ノードへのポインタを使用します。分類に便利で、子ノードを見つけるのは簡単ではありません。

第二に、コードの実装

単純なユニオン検索、初期化、マージ、およびクエリには、主に3つの関数があります。

初期化する方法はたくさんあります。すべてをそれ自体に初期化できます。これは、開始状態で各ノードを個別のツリーとして扱うのと同じです。これらのツリーにはルートノードが1つしかないため、すべてが自分自身を指します。すべて-1に初期化することもできます。この初期化の利点は、このセットの最上位ノードにあるノードの数を節約できることです。

void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=i;
}
//初始化为自己
void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=-1;
}
//初始化为-1

マージは初期化の方法によって異なり、微妙な違いがありますが、主な考え方は同じです。2つのノードがセットに含まれているかどうかを比較します。含まれていない場合は、マージできることを意味します。検索機能を使用して、セットのルートノードを作成し、1つのルートノードが別のルートノードを指すようにすると、マージ操作を完了できます。

void merge(int x,int y)
{
    
    
	int tx=find(x);
	int ty=find(y);
	if(tx!=ty)
		data[tx]=data[ty];
	//初始化为-1时可以补一句data[ty]+=data[tx],这样数组值的绝对值表示的就是集合中元素的个数
}

さまざまな初期化に応じて、さまざまな検索終了フラグを設定する必要があります。初期化を自己として使用する場合、検索の終了の兆候は、対応する位置の値がそれ自体の添え字に等しいことです。-1に初期化されると、検索の終了の兆候は、対応する位置の値がゼロ未満であることです。

int find(int x)
{
    
    
	while(data[x]!=x)
		x=data[x];
	return x;
}
//初始化为自己
int find(int x)
{
    
    
	while(data[x]>=0)
		x=data[x];
	return x;
}
int find(int n)
{
    
    
	if(pre[n]==n)
		return n;
	else
		return pre[n]=find(pre[n]);
}
//递归实现

コレクション自体を見つけることは難しくありません。BlueBridgeACMに携わっていた高齢者にとっては難しくありません。ただ、上向きに検索するプロセスを理解してください。完全なコードは次のとおりです

#include<bits/stdc++.h>
using namespace std;
int data[1005];
int m,n,choice=0;
void init()
{
    
    
	for(int i=1;i<=n;i++)
		data[i]=i;
}
int find(int x)
{
    
    
	while(data[x]!=x)
		x=data[x];
	return x;
}
void merge(int x,int y)
{
    
    
	int tx=find(x);
	int ty=find(y);
	if(tx!=ty)
		data[tx]=data[ty];
}
int main()
{
    
    
	scanf("%d %d",&m,&n);
	init();
	for(int i=0;i<m;i++)
	{
    
    
		int x,y;
		scanf("%d %d",&x,&y);
		merge(x,y);
	}
	scanf("%d",&choice);
	while(choice!=-1)
	{
    
    
		printf("%d\n",find(choice));
		scanf("%d",&choice);
	}
		 
	return 0;
 } 

おすすめ

転載: blog.csdn.net/weixin_43849505/article/details/107499141