Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
ProblemNależy zaprojektować strukturę zbiorów rozłącznych opartą na tablicy. |
Struktura zbiorów rozłącznych (ang. disjoint sets structure) pozwala reprezentować zbiory, które nie posiadają części wspólnych. Podstawowym problemem jest określenie sposobu rozpoznawania przynależności elementu do jednego z podzbiorów. Otóż umówmy się, że w każdym z podzbiorów wybierzemy dokładnie jeden element. Element ten będzie reprezentantem danego podzbioru.
Na powyższym rysunku widzimy cztery rozłączne zbiory. W każdym ze zbiorów
jeden element jest reprezentantem i oznaczyliśmy go kolorem czerwonym. Teraz
możemy powiedzieć, że są to zbiory
W strukturze zbiorów rozłącznych definiuje się zwykle dwie operacje:
Strukturę zbiorów rozłącznych można prosto zrealizować w postaci dwóch tablic o tym samym rozmiarze. W jednej tablicy przechowujemy elementy. W drugiej tablicy przechowujemy reprezentantów podzbiorów, zawierających poszczególne elementy. Nazwijmy te tablice odpowiednio E (elementy) i R (reprezentanci). W naszym przykładzie tablice te posiadają następującą zawartość:
|
|
Operacja Find otrzymuje indeks elementu w tablicy E i zwraca element o tym
indeksie z tablicy R. Wykonywana jest zatem w czasie stałym
Operacja Union jest tutaj bardziej skomplikowana. Otrzymuje ona indeksy
elementów x i y w tablicy
E. Najpierw Union musi sprawdzić, czy oba elementy
należą do różnych podzbiorów. W tym celu wykonuje Find(x) i Find(y),
zapamiętując wyniki
Jeśli elementy tworzą spójny zbiór wartości, to można uprościć strukturę
zbiorów rozłącznych do jednej
|
Operacja Find dla danego elementu (indeksu) zwraca
zawartość komórki tablicy R o tym indeksie, czyli zwraca reprezentanta
podzbioru, który zawiera dany element. Np.
Operacja Union(x, y) najpierw zapamiętuje w zmiennych
rx i ry odpowiednio
komórki
Na samym początku korzystania ze struktury zbiorów rozłącznych tablicę R należy odpowiednio zainicjować. W tym przypadku wystarczy wprowadzić do jej komórek ich indeksy. Będzie to odpowiadało utworzeniu n rozłącznych zbiorów jednoelementowych:
|
K01: Zakończ z wynikiem R[x]
K01: rx ← R[x] ; znajdujemy reprezentanta zbioru, który zawiera element x K02: ry ← R[y] ; znajdujemy reprezentanta zbioru, który zawiera element y K03: Jeśli rx = ry, ; elementy x i y muszą być w rozłącznych zbiorach to zakończ K04: Dla i = 0, 1, …, n-1: wykonuj krok K05 K05: Jeśli R[i] = ry, ; zastępujemy reprezentanta ry przez to R[i] ← rx ; rx dla wszystkich elementów K06: Zakończ
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
Program tworzy tablicę R 10-cio elementową, inicjuje ją, a następnie losuje 10 razy pary elementów. Dla wylosowanych elementów wykonywana jest operacja Union, co powoduje połączenie zbiorów, które te elementy zawierają. Na końcu wypisana zostaje przynależność każdego elementu do określonego podzbioru, liczba podzbiorów oraz zawartość tych podzbiorów. |
Pascal// Struktura zbiorów rozłącznych // Data: 25.03.2014 // (C)2014 mgr Jerzy Wałaszek //--------------------------- program DSStruct; const N = 10; // Liczba elementów var R : array [0..N-1] of integer; // Łączy dwa podzbiory w jeden //---------------------------- procedure Union(x, y : integer); var rx, ry, i : integer; begin rx := R[x]; // Wyznaczamy reprezentanta // zbioru zawierającego x ry := R[y]; // i reprezentanta zbioru // zawierającego y if rx <> ry then // Łączenie wymag // różnych zbiorów for i := 0 to N-1 do // Przeglądamy kolejne // elementy tablicy R if R[i] = ry then R[i] := rx; // i zastępujemy w nich // reprezentanta ry przez rx end; // ********************** // *** PROGRAM GŁÓWNY *** // ********************** var i, j, x, y, c : integer; begin Randomize; for i := 0 to N-1 do R[i] := i; // Ustawiamy tablicę R for i := 1 to N do begin x := random(N); // Generujemy losowe x i y y := random(N); Union(x, y); // Łączymy zbiory end; c := 0; // Licznik podzbiorów w R // Wyświetlamy wyniki for i := 0 to N-1 do begin if R[i] = i then inc(c); // Zliczamy reprezentantów writeln(i, ' is in set ', R[i]); end; writeln; writeln('Number of sets = ', c); writeln; for i := 0 to N-1 do if R[i] = i then begin write('Set ', i, ' : '); for j := 0 to N-1 do if R[j] = i then write(j, ' '); writeln; end; writeln; end. |
// Struktura zbiorów rozłącznych // Data: 25.03.2014 // (C)2014 mgr Jerzy Wałaszek //--------------------------- #include <iostream> #include <cstdlib> #include <ctime> using namespace std; const int N = 10; // Liczba elementów int R[N]; // Łączy dwa podzbiory w jeden //---------------------------- void Union(int x, int y) { int rx, ry, i; rx = R[x]; // Wyznaczamy reprezentanta zbioru // zawierającego x ry = R[y]; // i reprezentanta zbioru // zawierającego y if(rx != ry) // Łączenie wymaga różnych zbiorów for(i = 0; i < N; i++) // Przeglądamy kolejne // elementy tablicy R if(R[i] == ry) R[i] = rx; // i zastępujemy w nich // reprezentanta ry przez rx } // ********************** // *** PROGRAM GŁÓWNY *** // ********************** int main() { int i, j, x, y, c; srand(time(NULL)); for(i = 0; i < N; i++) R[i] = i; // Ustawiamy tablicę R for(i = 0; i < N; i++) { x = rand() % N; // Generujemy losowe x i y y = rand() % N; Union(x, y); // Łączymy zbiory } c = 0; // Licznik podzbiorów w R // Wyświetlamy wyniki for(i = 0; i < N; i++) { if(R[i] == i) |
Basic' Struktura zbiorów rozłącznych ' Data: 25.03.2014 ' (C)2014 mgr Jerzy Wałaszek '--------------------------- const N = 10 ' Liczba elementów Dim Shared As Integer R(0 To N-1) ' Łączy dwa podzbiory w jeden '---------------------------- sub union_sets (ByVal x As Integer, _ ByVal y As Integer) Dim As integer rx, ry, i rx = R(x) ' Wyznaczamy reprezentanta ' zbioru zawierającego x ry = R(y) ' i reprezentanta ' zbioru zawierającego y If rx <> ry Then ' Łączenie wymaga ' różnych zbiorów For i = 0 To N-1 ' Przeglądamy kolejne ' elementy tablicy R If R(i) = ry Then _ R(i) = rx ' i zastępujemy w nich ' reprezentanta ' ry przez rx Next End If End Sub ' ********************** ' *** PROGRAM GŁÓWNY *** ' ********************** dim As Integer i, j, x, y, c Randomize For i = 0 To N-1 R(i) = i ' Ustawiamy tablicę R Next For i = 0 To N-1 x = Int(Rnd*N) ' Generujemy losowe x i y y = Int(Rnd*N) union_sets(x, y) ' Łączymy zbiory Next c = 0 ' Licznik podzbiorów w R ' Wyświetlamy wyniki For i = 0 To N-1 If R(i) = i Then _ c += 1 ' Zliczamy reprezentantów Print i;" is in set ";R(i) Next Print Print "Number of sets =";c Print For i = 0 To N-1 If R(i) = i Then Print "Set";i;":"; For j = 0 To N-1 if R(j) = i Then Print j; Next Print End If Next Print End |
Python
(dodatek)# Struktura zbiorów rozłącznych # Data: 3.03.2024 # (C)2024 mgr Jerzy Wałaszek #--------------------------- import random N = 10 # Liczba elementów # Łączy dwa podzbiory w jeden # #---------------------------- def union_sets(r, x, y): # Wyznaczamy reprezentanta # zbioru zawierającego x rx = r[x] # i reprezentanta # zbioru zawierającego y ry = r[y] # Łączenie wymaga # różnych zbiorów if rx != ry: # Przeglądamy kolejne # elementy tablicy R for i in range(N): if r[i] == ry: # i zastępujemy w nich # reprezentanta # ry przez rx r[i] = rx # ********************** # *** PROGRAM GŁÓWNY *** # ********************** # Tworzymy zbiór set_r = [i for i in range(N)] for i in range(N): # Generujemy losowe x i y x = random.randrange(N) y = random.randrange(N) # Łączymy zbiory union_sets(set_r, x, y) # Licznik podzbiorów c = 0 # Wyświetlamy wyniki for i in range(N): if set_r[i] == i: c += 1 # Zliczamy reprezentantów print(i, "is in set", set_r[i]) print() print("Number of sets =", c) print() for i in range(N): if set_r[i] == i: print("Set", i, ": ", end="") for j in range(N): if set_r[j] == i: print(j, "", end="") print() print() |
Wynik: |
0 is in set 0 1 is in set 8 2 is in set 6 3 is in set 8 4 is in set 8 5 is in set 5 6 is in set 6 7 is in set 6 8 is in set 8 9 is in set 8 Number of sets = 4 Set 0 : 0 Set 5 : 5 Set 6 : 2 6 7 Set 8 : 1 3 4 8 9 |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.