Непересекающиеся множества
Непересекающиеся множества предназначены для выполнения запросов:
- Найти номер множества, в котором встречается данный элемент
- Объединить два множества в одно
Каждый элемент должен встречаться только в одном множестве.
Листинг Delphi
const DisetLength = 10000;
type Diset = object
public
p, rank : array[1..DisetLength] of integer;
public
constructor Create; overload;
constructor Create(N : integer); overload;
procedure MakeSet(x : integer);
procedure Union(x, y : integer);
procedure Link(x, y : integer);
function FindSet(x : integer) : integer;
end;
implementation
constructor Diset.Create;
begin
FillChar(rank, sizeof(rank), 0);
end;
constructor Diset.Create(N : integer); // Создание системы из n множеств
var i : integer;
begin
for i := 1 to N do
begin
p[i] := i;
rank[i] := 0;
end;
end;
procedure Diset.MakeSet(x : integer);
begin
p[x] := x;
rank[x] := 0;
end;
procedure Diset.Union(x, y : integer); // Объединение множеств, содержащих элементы x и y
begin
Link(FindSet(x), FindSet(y));
end;
procedure Diset.Link(x, y : integer);
begin
if rank[x] > rank[y]
then p[y] := x
else begin
p[x] := y;
if rank[x] = rank[y]
then inc(rank[y]);
end;
end;
function Diset.FindSet(x : integer) : integer; // Индекс множества, содержащего элемент
var y : integer;
begin
y := x;
while p[y] <> y
do y := p[y];
p[x] := y;
Result := y;
end;
Листинг C++
const int MaxN = 10000;
class diset
{
public:
int n;
int p[MaxN];
int r[MaxN];
int count;
diset(int _n);
int find(int i);
void link(int i, int j);
int size();
};
diset :: diset(int _n) // Создание системы из n множеств
{
n = _n;
count = _n;
for (int i = 0; i < n; ++ i)
{
p[i] = i;
r[i] = 0;
}
}
int diset :: find(int i) // Поиск множества, содержащего элемент i
{
if (i != p[i])
p[i] = find(p[i]);
return p[i];
}
void diset :: link(int i, int j) // Объединение двух множеств
{
count -= (find(i) != find(j));
if (r[find(i)] < r[find(j)])
p[find(i)] = p[find(j)];
else
{
p[find(j)] = p[find(i)];
if (r[find(i)] == r[find(j)])
++ r[find(i)];
}
}
08.12.2007, 18:37
По всем вопросам обращаться: rumterg@gmail.com