132 lines
2.1 KiB
C++
132 lines
2.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
class FDisjointSet
|
|
{
|
|
public:
|
|
FDisjointSet() {}
|
|
FDisjointSet( const uint32 Size );
|
|
|
|
void Init( uint32 Size );
|
|
void Reset();
|
|
void AddDefaulted( uint32 Num = 1 );
|
|
|
|
void Union( uint32 x, uint32 y );
|
|
void UnionSequential( uint32 x, uint32 y );
|
|
uint32 Find( uint32 i );
|
|
|
|
uint32 operator[]( uint32 i ) const { return Parents[i]; }
|
|
|
|
private:
|
|
TArray< uint32 > Parents;
|
|
};
|
|
|
|
FORCEINLINE FDisjointSet::FDisjointSet( const uint32 Size )
|
|
{
|
|
Init( Size );
|
|
}
|
|
|
|
FORCEINLINE void FDisjointSet::Init( uint32 Size )
|
|
{
|
|
Parents.SetNumUninitialized( Size, EAllowShrinking::No);
|
|
for( uint32 i = 0; i < Size; i++ )
|
|
{
|
|
Parents[i] = i;
|
|
}
|
|
}
|
|
|
|
FORCEINLINE void FDisjointSet::Reset()
|
|
{
|
|
Parents.Reset();
|
|
}
|
|
|
|
FORCEINLINE void FDisjointSet::AddDefaulted( uint32 Num )
|
|
{
|
|
uint32 Start = Parents.AddUninitialized( Num );
|
|
|
|
for( uint32 i = Start; i < Start + Num; i++ )
|
|
{
|
|
Parents[i] = i;
|
|
}
|
|
}
|
|
|
|
// Union with splicing
|
|
inline void FDisjointSet::Union( uint32 x, uint32 y )
|
|
{
|
|
uint32 px = Parents[x];
|
|
uint32 py = Parents[y];
|
|
|
|
while( px != py )
|
|
{
|
|
// Pick larger
|
|
if( px < py )
|
|
{
|
|
Parents[x] = py;
|
|
if( x == px )
|
|
{
|
|
return;
|
|
}
|
|
x = px;
|
|
px = Parents[x];
|
|
}
|
|
else
|
|
{
|
|
Parents[y] = px;
|
|
if( y == py )
|
|
{
|
|
return;
|
|
}
|
|
y = py;
|
|
py = Parents[y];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Optimized version of Union when iterating for( x : 0 to N ) unioning x with lower indexes.
|
|
// Neither x nor y can have already been unioned with an index > x.
|
|
inline void FDisjointSet::UnionSequential( uint32 x, uint32 y )
|
|
{
|
|
checkSlow( x >= y );
|
|
checkSlow( x == Parents[x] );
|
|
|
|
uint32 px = x;
|
|
uint32 py = Parents[y];
|
|
while( px != py )
|
|
{
|
|
Parents[y] = px;
|
|
if( y == py )
|
|
{
|
|
return;
|
|
}
|
|
y = py;
|
|
py = Parents[y];
|
|
}
|
|
}
|
|
|
|
// Find with path compression
|
|
inline uint32 FDisjointSet::Find( uint32 i )
|
|
{
|
|
// Find root
|
|
uint32 Start = i;
|
|
uint32 Root = Parents[i];
|
|
while( Root != i )
|
|
{
|
|
i = Root;
|
|
Root = Parents[i];
|
|
}
|
|
|
|
// Point all nodes on path to root
|
|
i = Start;
|
|
uint32 Parent = Parents[i];
|
|
while( Parent != Root )
|
|
{
|
|
Parents[i] = Root;
|
|
i = Parent;
|
|
Parent = Parents[i];
|
|
}
|
|
|
|
return Root;
|
|
} |