Disjoint set

Il disjoint set memorizza una collezione di sottoinsiemi disgiunti di un insieme generativo. Ammette operazioni di ricerca e unione, ma non inserzione e cancellazione.

Un insieme generativo è un insieme del tipo . I sottoinsiemi disgiunti sono sottoinsiemi di un insieme generativo, del tipo tale che

Primitive

  • make-set(X): restituisce un disjoint set in cui -
  • find-set(DS, x): restituisce un rappresentante dell’insieme a cui appartieen x -
  • union(DS, x, y): unisce gli insiemi a cui appartengono x, y -

Ogni insieme è rappresentato da un albero, e quindi per ogni insieme esiste un rappresentante che fa da radice dell’albero.

make-set(X):
	DS := new_array[1..n]
	for i=1 to n do
		DS[i] := 1
	return DS

Costo computazionale

find-set(DS, x):
	if DS[x] = x then
		return x
	else
		return find-set(DS, DS[x])

Costo computazionale lineare all’altezza dell’albero.

union(DS, x, y):
	xr := find-set(DS, x)
	yr := find-set(DS, y)
	if xr != yr then
		DS[xr] := yr

Anche in questo caso il costo computazionale è lineare all’altezza dei due alberi, quindi il costo è di

Rango

Ogni albero ha un rango, che rappresenta la sua altezza. Il Disjoint set, quindi, mantiene un array di rank, e un array di padri.

make-set(X):
	DS.p := new_array[1..n]
	DS.rank := new_array[1..n]
	for i=1 to n do
		DS.p[i] := 1
		DS.rank := 0
	return DS
find-set(DS, x):
	if DS.p[x] = x then
		return x
	else
		return find-set(DS, DS[x])
union(DS, x, y):
	xr := find-set(DS, x)
	yr := find-set(DS, y)
	if xr != yr then
		if DS.rank[xr] > DS.rank[yr] then
			DS.p[yr] := xr
		else
			DS.p[xr] := yr
			if DS.rank[xr] = DS.rank[yr] then
				DS.rank[yr] := DS.rank[yr] + 1

Utilizzando l’euristica del rango, un albero della foresta con radice r ha almeno nodi, quindi un albero di radice r con k nodi ha

Il costo computazionale di find e union, usando il rango, è di .

Perchè? Caso base: subito dopo make-set, prima della union si ha

  • ogni albero ha esattamente un nodo
  • per ogni nodo r si ha rank[r] = 0

Ipotesi induttiva: dopo operazioni union, per un albero di nodi con rappresentante r vale che . Per xr = yr è vero. Se invece xr != yr, allora

  • rank[xr] > rank[yr]: xr diventa il rappresentante di yr, ma il rango no cambia
  • rank[xr] < rank[yr]: yr diventa il rappresentante di xr, ma il rango no cambia
  • rank[xr] = rank[yr]: make-set costa sempre , mentre union e find-set costano

asd_35